views.py 22 KB
Newer Older
1
2
3
4
# standard library imports
from datetime import date
from cStringIO import StringIO
# core django imports
Daniel W Bond's avatar
Daniel W Bond committed
5
6
from django.views.generic import View, DetailView, ListView, CreateView,\
    UpdateView, DeleteView
7
from django.http import Http404, HttpResponseForbidden
8
from django.forms.widgets import HiddenInput
9
from django.core.urlresolvers import reverse
10
from django.core.files.uploadedfile import SimpleUploadedFile
11
12
13
from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template
from django.template import Context
14
from django.contrib import messages
15
from django.utils.safestring import mark_safe
16
# third party imports
17
import requests
18
from PIL import Image
19
from braces.views import LoginRequiredMixin
20
from braces.views import FormValidMessageMixin
Daniel W Bond's avatar
Daniel W Bond committed
21
from ratelimit.decorators import ratelimit
22
23
# imports from your apps
from .models import Listing, Bid, Flag, Rating
24
25
from .forms import ListingForm, BidForm, FlagForm, SellListingForm,\
    UnSellListingForm, RatingForm
26
from core.models import Student
27

Daniel W Bond's avatar
Daniel W Bond committed
28

29
30
# pulls worldcat metadata from ISBNs
def ISBNMetadata(standardISBN):
31
    # passing in numbers starting with 0 throws "SyntaxError: invalid token"
32
33
34
35
36
37
38
39
40
41
    url = "http://xisbn.worldcat.org/webservices/xid/isbn/" + str(standardISBN) + "?method=getMetadata&format=json&fl=title,year,author,ed"
    metadata = requests.get(url)
    # format into a dictionary
    dejson = metadata.json()
    try:
        metadataDict = dejson.get('list')
        return metadataDict[0]
    except:
        return None

Daniel W Bond's avatar
Daniel W Bond committed
42

43
44
45
# flagging
# you can only flag a listing once...
def can_flag(flagger, listing):
Daniel W Bond's avatar
Daniel W Bond committed
46
47
    user_flag_num = Flag.objects.filter(flagger=flagger,
                                        listing=listing).count()
48
49
50
51
52
53
    # we're assuming that this isn't going to go over 1
    if user_flag_num:
        return False
    else:
        return True

Daniel W Bond's avatar
Daniel W Bond committed
54

55
56
57
58
59
60
61
# get the listing's slug to pass to the create flag page
def flag_slug(flagger, listing):
    if not can_flag(flagger, listing):
        return Flag.objects.get(flagger=flagger, listing=listing).slug
    else:
        return None

62

Daniel W Bond's avatar
Daniel W Bond committed
63
64
65
66
67
68
69
70
71
72
73
74
# rating
# (basically) duplicated code!!!
def can_rate(rater, listing):
    user_rate_num = Rating.objects.filter(rater=rater,
                                           listing=listing).count()
    # we're assuming that this isn't going to go over 1
    if user_rate_num:
        return False
    else:
        return True


Daniel W Bond's avatar
Daniel W Bond committed
75
76
77
class ListListings(LoginRequiredMixin, ListView):
    model = Listing
    context_object_name = 'listings'
78
    paginate_by = 16
Daniel W Bond's avatar
Daniel W Bond committed
79
    queryset = Listing.objects.exclude(cancelled=True).order_by('-created')
80
    template_name = 'list_listings.html'
81
    login_url = 'login'
82

Daniel W Bond's avatar
Daniel W Bond committed
83

84
class CreateListing(LoginRequiredMixin, FormValidMessageMixin, CreateView):
85
    model = Listing
Daniel W Bond's avatar
Daniel W Bond committed
86
87
    fields = ['isbn', 'title', 'author', 'edition', 'year', 'course_abbr',
              'condition', 'access_code', 'price', 'photo', 'description']
88
89
90
    template_name = 'create_listing.html'
    context_object_name = 'listing'
    # ISBN query!
91
    login_url = 'login'
92

93
    # eventually figure out how to use {% url 'create_listing' %}
94
95
    form_valid_message = mark_safe("""Your listing was successfully created!
                         <a href="/share/new/">Create another here!</a>""")
96

97
    def form_valid(self, form):
98
99
        me = Student.objects.get(user=self.request.user)

100
        form.instance.seller = me
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

        image_name = form.instance.photo.name
        user_image = Image.open(form.instance.photo)
        image_format = user_image.format

        print user_image
        width, height = user_image.size
        print user_image.size
        print width, "width"
        print height, "height"
        maxsize = (2560, 1920)
        # five megapixels is 2560x1920
        if (width > 2560) or (height > 1920):
            user_image.thumbnail(maxsize)

            temp_image = StringIO()
            user_image.save(temp_image, image_format)
            temp_image.seek(0)

            new_uploaded_file = SimpleUploadedFile(image_name,
                            temp_image.read(), content_type=image_format)

            form.instance.photo = new_uploaded_file

125
        return super(CreateListing, self).form_valid(form)
126

127
128
    def get_context_data(self, **kwargs):
        context = super(CreateListing, self).get_context_data(**kwargs)
129

130
131
        form = ListingForm()
        context['my_form'] = form
132
133
        return context

Daniel W Bond's avatar
Daniel W Bond committed
134
135
136
137
138
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    @ratelimit(key='user', rate='100/day', method='POST', block=True)
    def post(self, request, *args, **kwargs):
        return super(CreateListing, self).post(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
139

140
141
# These next two views are tied together...
class DetailListing(DetailView):
142
143
    model = Listing
    context_object_name = 'listing'
144
    template_name = 'detail_listing.html'
145

Daniel W Bond's avatar
Daniel W Bond committed
146
147
    def get_context_data(self, **kwargs):
        context = super(DetailListing, self).get_context_data(**kwargs)
148
        me = Student.objects.get(user=self.request.user)
149
150

        # make the form available to the template on get
151
        # set the bidder and the listing
152
        form = BidForm(initial={'listing': self.get_object()})
153
        form.fields['listing'].widget = HiddenInput()
154
155
        context['my_form'] = form

Daniel W Bond's avatar
Daniel W Bond committed
156
157
158
159
160
        try:
            context['rating'] = Rating.objects.get(listing=self.get_object())
        except:
            context['rating'] = False

Daniel W Bond's avatar
Daniel W Bond committed
161
        # bids, filter by listing name of the current listing, order by date created
162
        context['bids'] = Bid.objects.filter(listing=self.get_object()).order_by('-price')
163
164
165
166
        context['bid_count'] = Bid.objects.filter(listing=self.get_object).count()
        # flags
        context['flags'] = Flag.objects.filter(listing=self.get_object()).order_by('-created')
        context['flag_count'] = Flag.objects.filter(listing=self.get_object()).count()
167
168
        context['can_flag'] = can_flag(me, self.get_object())
        context['flag_slug'] = flag_slug(me, self.get_object())
Daniel W Bond's avatar
Daniel W Bond committed
169
170
        return context

171

172
173
class CreateBid(CreateView):
    model = Bid
Daniel W Bond's avatar
Daniel W Bond committed
174
    fields = ['listing', 'price', 'text', ]
175
    context_object_name = 'bid'
176
    template_name = 'detail_listing.html'
177

178
179
180
181
182
183
    def form_valid(self, form):
        me = Student.objects.get(user=self.request.user)

        form.instance.bidder = me
        return super(CreateBid, self).form_valid(form)

184
    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
185
186
187
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})

188

189
190
# ...to make this single view
class ListingPage(LoginRequiredMixin, View):
191
    login_url = 'login'
192
193
194
195
196
197
198
199

    # see this page for an explanation
    # https://docs.djangoproject.com/en/1.7/topics/class-based-views/mixins/#an-alternative-better-solution

    def get(self, request, *args, **kwargs):
        view = DetailListing.as_view()
        return view(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
200
201
202
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    # rate limit is higher for bids
    @ratelimit(key='user', rate='200/d', method='POST', block=True)
203
204
205
206
    def post(self, request, *args, **kwargs):
        view = CreateBid.as_view()
        return view(request, *args, **kwargs)

207

Daniel W Bond's avatar
Daniel W Bond committed
208
# and we return to our regularly schedule programming
209
210
class CreateFlag(LoginRequiredMixin, CreateView):
    model = Flag
Daniel W Bond's avatar
Daniel W Bond committed
211
    fields = ['reason', ]
212
    template_name = 'create_flag.html'
213
    context_object_name = 'flag'
214
    login_url = 'login'
215

216
217
218
219
220
221
222
223
224
225
226
227
    def form_valid(self, form):
        me = Student.objects.get(user=self.request.user)

        current_url = self.request.get_full_path()
        listing_slug = current_url.split('/')[3]
        # [u'', u'share', u'listing', u'C1s3oD', u'flag']
        selected_listing = Listing.objects.get(slug=listing_slug)

        form.instance.flagger = me
        form.instance.listing = selected_listing
        return super(CreateFlag, self).form_valid(form)

228
    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
229
230
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})
231
232
233
234
235

    def get_context_data(self, **kwargs):
        context = super(CreateFlag, self).get_context_data(**kwargs)
        me = Student.objects.get(user=self.request.user)

236
        # duplicated code!!!
237
238
239
240
241
242
243
244
245
        current_url = self.request.get_full_path()
        listing_slug = current_url.split('/')[3]
        # [u'', u'share', u'listing', u'C1s3oD', u'flag']
        selected_listing = Listing.objects.get(slug=listing_slug)

        selling_student = selected_listing.seller

        # you can't flag your own listing
        if (selling_student == me):
246
            return HttpResponseForbidden()
247
248
249

        # can only create a flag if you haven't previously created one
        if not can_flag(me, selected_listing):
250
251
            # because the page shouldn't exist in this scenario
            raise Http404
252
253

        context['listing'] = selected_listing
254
255
256

        form = FlagForm()
        context['my_form'] = form
257
258
        return context

Daniel W Bond's avatar
Daniel W Bond committed
259
260
261
262
263
    # no daily limit because we want people to flag everything they need to
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    def post(self, request, *args, **kwargs):
        return super(CreateFlag, self).post(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
264

265
266
class DeleteFlag(LoginRequiredMixin, DeleteView):
    model = Flag
267
    context_object_name = 'flag'
268
    template_name = 'delete_flag.html'
269
    login_url = 'login'
270
271

    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
272
273
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})
274
275
276
277
278

    def get_context_data(self, **kwargs):
        context = super(DeleteFlag, self).get_context_data(**kwargs)
        me = Student.objects.get(user=self.request.user)

279
        flag_student = self.get_object().flagger
280

281
282
283
        # if you didn't create the flag, you can't delete the flag
        if not(me == flag_student):
            return HttpResponseForbidden()
284
285
286

        return context

Daniel W Bond's avatar
Daniel W Bond committed
287

288
# not implemented -- tbd
289
290
291
292
293
294
class DeleteBid(LoginRequiredMixin, DeleteView):
    model = Bid
    success_url = '/'

    # can be deleted by either creator or person for lister

Daniel W Bond's avatar
Daniel W Bond committed
295

Daniel W Bond's avatar
Daniel W Bond committed
296
class EditBid(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
297
    model = Bid
Daniel W Bond's avatar
Daniel W Bond committed
298
299
300
301
302
    template_name = 'bid_edit.html'
    context_object_name = 'bid'
    #form_class = EditBidForm
    login_url = 'login'

303
    form_valid_message = "Your bid was successfully updated!"
Daniel W Bond's avatar
Daniel W Bond committed
304
305
306

    fields = ['price', 'text', ]

307
308
    success_url = '/'

Daniel W Bond's avatar
Daniel W Bond committed
309
310
311
312
313
314
315
316
317
318
319
320
321
322
    def get_success_url(self):
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug })

    def get_context_data(self, **kwargs):
        context = super(EditBid, self).get_context_data(**kwargs)

        me = Student.objects.get(user=self.request.user)

        bidding_student = self.get_object().bidder

        if not(bidding_student == me):
            return HttpResponseForbidden()

323
324
        # if sold or cancelled, this page doesn't exist
        if self.get_object().listing.sold or self.get_object().listing.cancelled:
Daniel W Bond's avatar
Daniel W Bond committed
325
326
327
            raise Http404

        return context
328

Daniel W Bond's avatar
Daniel W Bond committed
329

330
class EditListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
Daniel W Bond's avatar
Daniel W Bond committed
331
    model = Listing
332
333
    template_name = 'listing_edit.html'
    context_object_name = 'listing'
334
    #form_class = EditListingForm
335
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
336

337
    form_valid_message = "Your listing was successfully updated!"
338

Daniel W Bond's avatar
Daniel W Bond committed
339
340
    fields = ['title', 'author', 'isbn', 'year', 'edition', 'condition',
              'access_code', 'description', 'price', 'photo', ]
341
342
343
344
345
    template_suffix_name = '_edit'

    def get_context_data(self, **kwargs):
        context = super(EditListing, self).get_context_data(**kwargs)

346
347
        me = Student.objects.get(user=self.request.user)
        selling_student = self.get_object().seller
348

349
        if not(selling_student == me):
350
            return HttpResponseForbidden()
351

Daniel W Bond's avatar
Daniel W Bond committed
352
353
        return context

354

Daniel W Bond's avatar
Daniel W Bond committed
355
class SellListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
356
    model = Listing
Daniel W Bond's avatar
Daniel W Bond committed
357
    fields = ['email_message', 'winning_bid', ]
358
    template_suffix_name = '_sell'
359
360
    context_object_name = 'listing'
    template_name = 'listing_sell.html'
361
    login_url = 'login'
362

363
    form_valid_message = "Your email was successfully sent!"
364

365
    def form_valid(self, form):
366
        # filling out fields
367
        today = date.today()
368
        self.obj = self.get_object()
369
370
371

        form.instance.sold = True
        form.instance.date_closed = today
372
373

        # sending email
Daniel W Bond's avatar
Daniel W Bond committed
374
        # I'm still second guessing as to whether this should be in this method
375
376
377
        text_email = get_template('email/sold.txt')
        html_email = get_template('email/sold.html')

Daniel W Bond's avatar
Daniel W Bond committed
378
379
380
381
382
383
384
        email_context = Context({
            'bidder_first_name': form.instance.winning_bid.bidder.user.first_name,
            'seller_name': self.obj.seller.user.get_full_name(),
            'bid_num': form.instance.winning_bid.price,
            'listing_title': self.obj.title,
            'seller_email': self.obj.seller.user.email,
            'email_message': form.instance.email_message, })
385

Daniel W Bond's avatar
Daniel W Bond committed
386
        subject, from_email, to, cc = ('Your bid has been selected on Bookshare!',
Daniel W Bond's avatar
Daniel W Bond committed
387
                                       'no-reply@bookshare.srct.io',
388
389
390
391
                                       #form.instance.winning_bid.bidder.user.email,
                                       #self.obj.seller.user.email)
                                       'success@simulator.amazonses.com',
                                       'success@simulator.amazonses.com')
392
        text_content = text_email.render(email_context)
393
        html_content = html_email.render(email_context)
Daniel W Bond's avatar
Daniel W Bond committed
394
395
        msg = EmailMultiAlternatives(subject, text_content,
                                     from_email, [to], [cc])
396
        msg.attach_alternative(html_content, "text/html")
397
398
        msg.send()

399
400
        return super(SellListing, self).form_valid(form)

401
402
403
    def get_context_data(self, **kwargs):
        context = super(SellListing, self).get_context_data(**kwargs)

404
405
        me = Student.objects.get(user=self.request.user)
        selling_student = self.get_object().seller
406

407
        if not(selling_student == me):
408
            return HttpResponseForbidden()
409

410
411
        bid_count = Bid.objects.filter(listing=self.get_object).count()
        if bid_count < 1:
412
            # because the page shouldn't exist in this scenario
Daniel W Bond's avatar
Daniel W Bond committed
413
414
            raise Http404

415
        form = SellListingForm()
416
417
418
419
        form.fields['winning_bid'].queryset = Bid.objects.filter(listing=self.get_object())

        context['my_form'] = form

Daniel W Bond's avatar
Daniel W Bond committed
420
421
        return context

Daniel W Bond's avatar
Daniel W Bond committed
422
423
424
425
426
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
    def post(self, request, *args, **kwargs):
        return super(SellListing, self).post(request, *args, **kwargs)

427

428
class UnSellListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
429
    model = Listing
430
    fields = ['email_message', ]
431
    template_suffix_name = '_unsell'
432
433
    context_object_name = 'listing'
    template_name = 'listing_unsell.html'
434
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
435

436
    form_valid_message = """Your sale has been successfully cancelled,
437
                     and your email successfully sent!"""
438

439
    def form_valid(self, form):
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
        self.obj = self.get_object()
        text_email = get_template('email/unsold.txt')
        html_email = get_template('email/unsold.html')

        email_context = Context({
            'bidder_first_name': self.obj.winning_bid.bidder.user.first_name,
            'seller_name': self.obj.seller.user.get_full_name(),
            'bid_num': self.obj.winning_bid.price,
            'listing_title': self.obj.title,
            'seller_email': self.obj.seller.user.email,
            'seller_email': form.instance.email_message, })

        subject, from_email, to, cc = ('Your transaction has been cancelled on Bookshare',
                                       'no-reply@bookshare.srct.io',
                                       #self.obj.winning_bid.bidder.user.email,
                                       #self.obj.seller.user.email)
                                       'success@simulator.amazonses.com',
                                       'success@simulator.amazonses.com')
        text_content = text_email.render(email_context)
        html_content = html_email.render(email_context)
        msg = EmailMultiAlternatives(subject, text_content,
                                     from_email, [to], [cc])
        msg.attach_alternative(html_content, "text/html")
        msg.send()

        # this has to come after the email has been sent, otherwise these are
        # cleaned out 
467
468
469
        form.instance.sold = False
        form.instance.date_closed = None
        form.instance.winning_bid = None
470

471
472
        return super(UnSellListing, self).form_valid(form)

Daniel W Bond's avatar
Daniel W Bond committed
473
    def get_context_data(self, **kwargs):
474
        context = super(UnSellListing, self).get_context_data(**kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
475

476
477
        me = Student.objects.get(user=self.request.user)
        selling_student = self.get_object().seller
Daniel W Bond's avatar
Daniel W Bond committed
478

479
        if not(selling_student == me):
480
            return HttpResponseForbidden()
Daniel W Bond's avatar
Daniel W Bond committed
481

482
483
484
        form = UnSellListingForm()
        context['my_form'] = form

Daniel W Bond's avatar
Daniel W Bond committed
485
        return context
Daniel W Bond's avatar
Daniel W Bond committed
486
487
488
489
490
 
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
    def post(self, request, *args, **kwargs):
        return super(UnSellListing, self).post(request, *args, **kwargs)
491

Daniel W Bond's avatar
Daniel W Bond committed
492

493
class CancelListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
Daniel W Bond's avatar
Daniel W Bond committed
494
    model = Listing
495
    fields = []
496
    template_suffix_name = '_cancel'
497
498
    context_object_name = 'listing'
    template_name = 'listing_cancel.html'
499
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
500

501
502
    form_valid_message = "Your listing was successfully cancelled!"

503
504
505
506
507
508
509
    def form_valid(self, form):
        today = date.today()

        form.instance.cancelled = True
        form.instance.date_closed = today
        return super(CancelListing, self).form_valid(form)

Daniel W Bond's avatar
Daniel W Bond committed
510
    def get_context_data(self, **kwargs):
511
        context = super(CancelListing, self).get_context_data(**kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
512

513
514
        me = Student.objects.get(user=self.request.user)
        selling_student = self.get_object().seller
Daniel W Bond's avatar
Daniel W Bond committed
515

516
        if not(selling_student == me):
517
            return HttpResponseForbidden()
Daniel W Bond's avatar
Daniel W Bond committed
518

Daniel W Bond's avatar
Daniel W Bond committed
519
        return context
520

Daniel W Bond's avatar
Daniel W Bond committed
521

522
class ReopenListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
523
    model = Listing
524
    fields = []
525
    template_suffix_name = '_reopen'
526
527
    context_object_name = 'listing'
    template_name = 'listing_reopen.html'
528
    login_url = 'login'
529

530
    form_valid_message = "Your listing was successfully reopened!"
531

532
533
534
535
536
    def form_valid(self, form):
        form.instance.cancelled = False
        form.instance.date_closed = None
        return super(ReopenListing, self).form_valid(form)

537
538
539
    def get_context_data(self, **kwargs):
        context = super(ReopenListing, self).get_context_data(**kwargs)

540
541
        me = Student.objects.get(user=self.request.user)
        selling_student = self.get_object().seller
542

543
        if not(selling_student == me):
544
            return HttpResponseForbidden()
545

Daniel W Bond's avatar
Daniel W Bond committed
546
        return context
Daniel W Bond's avatar
Daniel W Bond committed
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598


class CreateRating(LoginRequiredMixin, CreateView):
    model = Rating
    fields = ['stars', 'review', ]
    template_name = 'create_rating.html'
    context_object_name = 'rating'
    login_url = 'login'

    def form_valid(self, form):
        me = Student.objects.get(user=self.request.user)

        current_url = self.request.get_full_path()
        listing_slug = current_url.split('/')[3]
        # [u'', u'share', u'listing', u'C1s3oD', u'flag']
        selected_listing = Listing.objects.get(slug=listing_slug)

        form.instance.rater = me
        form.instance.listing = selected_listing
        return super(CreateRating, self).form_valid(form)

    def get_success_url(self):
        return reverse('ratings',
                       kwargs={'slug': self.object.listing.seller.slug})

    def get_context_data(self, **kwargs):
        context = super(CreateRating, self).get_context_data(**kwargs)
        me = Student.objects.get(user=self.request.user)

        # duplicated code!!!
        current_url = self.request.get_full_path()
        listing_slug = current_url.split('/')[3]
        # [u'', u'share', u'listing', u'C1s3oD', u'flag']
        selected_listing = Listing.objects.get(slug=listing_slug)

        winning_student = selected_listing.winning_bid.bidder

        # you can only rate a listing that you won
        if not (winning_student == me):
            return HttpResponseForbidden()

        # can only create a rating if you haven't previously created one
        if not can_rate(me, selected_listing):
            # because the page shouldn't exist in this scenario
            raise Http404

        context['listing'] = selected_listing

        form = RatingForm()
        context['my_form'] = form
        return context

Daniel W Bond's avatar
Daniel W Bond committed
599
600
601
602
603
    # no per-day limit because you can only rate listings you've been sold to
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    def post(self, request, *args, **kwargs):
        return super(CreateRating, self).post(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651

class EditRating(LoginRequiredMixin, UpdateView):
    model = Rating
    template_name = 'rating_edit.html'
    context_object_name = 'rating'
    #form_class = EditListingForm
    login_url = 'login'

    fields = ['stars', 'review', ]

    template_suffix_name = '_edit'

    def get_success_url(self):
        return reverse('ratings',
                       kwargs={'slug': self.object.listing.seller.slug})

    def get_context_data(self, **kwargs):
        context = super(EditRating, self).get_context_data(**kwargs)

        me = Student.objects.get(user=self.request.user)
        rating_student = self.get_object().rater

        if not(rating_student == me):
            return HttpResponseForbidden()

        return context


class DeleteRating(LoginRequiredMixin, DeleteView):
    model = Rating
    context_object_name = 'rating'
    template_name = 'delete_rating.html'
    login_url = 'login'

    def get_success_url(self):
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})

    def get_context_data(self, **kwargs):
        context = super(DeleteRating, self).get_context_data(**kwargs)

        me = Student.objects.get(user=self.request.user)
        rating_student = self.get_object().rater

        if not(rating_student == me):
            return HttpResponseForbidden()

        return context