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.utils.safestring import mark_safe
15
# third party imports
16
import requests
17
from PIL import Image
18
from braces.views import LoginRequiredMixin
19
from braces.views import FormValidMessageMixin
Daniel W Bond's avatar
Daniel W Bond committed
20
from ratelimit.decorators import ratelimit
21
22
# imports from your apps
from .models import Listing, Bid, Flag, Rating
23
24
from .forms import ListingForm, BidForm, FlagForm, ExchangeListingForm,\
    UnExchangeListingForm, RatingForm
25
from core.models import Student
26

Daniel W Bond's avatar
Daniel W Bond committed
27

28
29
# pulls worldcat metadata from ISBNs
def ISBNMetadata(standardISBN):
30
    # passing in numbers starting with 0 throws "SyntaxError: invalid token"
Daniel W Bond's avatar
Daniel W Bond committed
31
32
33
    url = "http://xisbn.worldcat.org/webservices/xid/isbn/" +\
          str(standardISBN) +\
          "?method=getMetadata&format=json&fl=title,year,author,ed"
34
35
36
37
38
39
40
41
42
    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
43

44
45
46
# flagging
# you can only flag a listing once...
def can_flag(flagger, listing):
Daniel W Bond's avatar
Daniel W Bond committed
47
48
    user_flag_num = Flag.objects.filter(flagger=flagger,
                                        listing=listing).count()
49
50
51
52
53
54
    # 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
55

56
57
58
59
60
61
62
# 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

63

Daniel W Bond's avatar
Daniel W Bond committed
64
65
66
67
# rating
# (basically) duplicated code!!!
def can_rate(rater, listing):
    user_rate_num = Rating.objects.filter(rater=rater,
Daniel W Bond's avatar
Daniel W Bond committed
68
                                          listing=listing).count()
Daniel W Bond's avatar
Daniel W Bond committed
69
70
71
72
73
74
75
    # 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
76
77
78
class ListListings(LoginRequiredMixin, ListView):
    model = Listing
    context_object_name = 'listings'
79
    paginate_by = 16
Daniel W Bond's avatar
Daniel W Bond committed
80
    queryset = Listing.objects.exclude(cancelled=True).order_by('-created')
81
    template_name = 'list_listings.html'
82
    login_url = 'login'
83

Daniel W Bond's avatar
Daniel W Bond committed
84

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

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

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

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

        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,
Daniel W Bond's avatar
Daniel W Bond committed
122
                                    temp_image.read(), content_type=image_format)
123
124
125

            form.instance.photo = new_uploaded_file

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

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

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

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

Daniel W Bond's avatar
Daniel W Bond committed
140

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

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

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

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

Daniel W Bond's avatar
Daniel W Bond committed
162
        # bids, filter by listing name of the current listing, order by date created
163
        context['bids'] = Bid.objects.filter(listing=self.get_object()).order_by('-price')
164
165
166
167
        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()
168
169
        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
170
171
        return context

172

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

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

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

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

189

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

    # 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
201
202
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    # rate limit is higher for bids
203
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
204
205
206
207
    def post(self, request, *args, **kwargs):
        view = CreateBid.as_view()
        return view(request, *args, **kwargs)

208

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

217
218
219
220
221
222
223
224
225
226
227
228
    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)

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

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

237
        # duplicated code!!!
238
239
240
241
242
        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)

243
        posting_student = selected_listing.poster
244
245

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

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

        context['listing'] = selected_listing
255
256
257

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

Daniel W Bond's avatar
Daniel W Bond committed
260
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
261
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
Daniel W Bond's avatar
Daniel W Bond committed
262
263
264
    def post(self, request, *args, **kwargs):
        return super(CreateFlag, self).post(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
265

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

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

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

280
        flag_student = self.get_object().flagger
281

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

        return context

Daniel W Bond's avatar
Daniel W Bond committed
288

289
# not implemented -- tbd
290
291
292
293
294
295
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
296

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

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

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

308
309
    success_url = '/'

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

    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()

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

        return context
329

Daniel W Bond's avatar
Daniel W Bond committed
330

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

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

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

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

347
        me = Student.objects.get(user=self.request.user)
348
        posting_student = self.get_object().poster
349

350
        if not(posting_student == me):
351
            return HttpResponseForbidden()
352

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

355

356
class ExchangeListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
357
    model = Listing
Daniel W Bond's avatar
Daniel W Bond committed
358
    fields = ['email_message', 'winning_bid', ]
359
    context_object_name = 'listing'
360
    template_name = 'listing_exchange.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
        form.instance.exchanged = True
371
        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
        text_email = get_template('email/exchanged.txt')
        html_email = get_template('email/exchanged.html')
377

Daniel W Bond's avatar
Daniel W Bond committed
378
379
        email_context = Context({
            'bidder_first_name': form.instance.winning_bid.bidder.user.first_name,
380
            'poster_name': self.obj.poster.user.get_full_name(),
Daniel W Bond's avatar
Daniel W Bond committed
381
382
            'bid_num': form.instance.winning_bid.price,
            'listing_title': self.obj.title,
383
            'poster_email': self.obj.poster.user.email,
Daniel W Bond's avatar
Daniel W Bond committed
384
            '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',
Daniel W Bond's avatar
Daniel W Bond committed
388
                                       # form.instance.winning_bid.bidder.user.email,
389
                                       # self.obj.poster.user.email)
390
391
                                       '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
        return super(ExchangeListing, self).form_valid(form)
400

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

404
        me = Student.objects.get(user=self.request.user)
405
        posting_student = self.get_object().poster
406

407
        if not(posting_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 = ExchangeListingForm()
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
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
423
    @ratelimit(key='user', rate='50/d', method='POST', block=True)
Daniel W Bond's avatar
Daniel W Bond committed
424
    def post(self, request, *args, **kwargs):
425
        return super(ExchangeListing, self).post(request, *args, **kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
426

427

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

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

438
    def form_valid(self, form):
439
        self.obj = self.get_object()
440
441
        text_email = get_template('email/unexchanged.txt')
        html_email = get_template('email/unexchanged.html')
442
443
444

        email_context = Context({
            'bidder_first_name': self.obj.winning_bid.bidder.user.first_name,
445
            'poster_name': self.obj.poster.user.get_full_name(),
446
447
            'bid_num': self.obj.winning_bid.price,
            'listing_title': self.obj.title,
448
449
            'poster_email': self.obj.poster.user.email,
            'poster_email': form.instance.email_message, })
450
451
452

        subject, from_email, to, cc = ('Your transaction has been cancelled on Bookshare',
                                       'no-reply@bookshare.srct.io',
Daniel W Bond's avatar
Daniel W Bond committed
453
                                       # self.obj.winning_bid.bidder.user.email,
454
                                       # self.obj.poster.user.email)
455
456
457
458
459
460
461
462
463
464
                                       '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
Daniel W Bond's avatar
Daniel W Bond committed
465
        # cleaned out
466
        form.instance.exchanged = False
467
468
        form.instance.date_closed = None
        form.instance.winning_bid = None
469

470
        return super(UnExchangeListing, self).form_valid(form)
471

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

475
        me = Student.objects.get(user=self.request.user)
476
        posting_student = self.get_object().poster
Daniel W Bond's avatar
Daniel W Bond committed
477

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

481
        form = UnExchangeListingForm()
482
483
        context['my_form'] = form

Daniel W Bond's avatar
Daniel W Bond committed
484
        return context
Daniel W Bond's avatar
Daniel W Bond committed
485

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

Daniel W Bond's avatar
Daniel W Bond committed
491

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

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

502
503
504
505
506
507
508
    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
509
    def get_context_data(self, **kwargs):
510
        context = super(CancelListing, self).get_context_data(**kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
511

512
        me = Student.objects.get(user=self.request.user)
513
        posting_student = self.get_object().poster
Daniel W Bond's avatar
Daniel W Bond committed
514

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

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

Daniel W Bond's avatar
Daniel W Bond committed
520

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

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

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

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

539
        me = Student.objects.get(user=self.request.user)
540
        posting_student = self.get_object().poster
541

542
        if not(posting_student == me):
543
            return HttpResponseForbidden()
544

Daniel W Bond's avatar
Daniel W Bond committed
545
        return context
Daniel W Bond's avatar
Daniel W Bond committed
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568


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',
569
                       kwargs={'slug': self.object.listing.poster.slug})
Daniel W Bond's avatar
Daniel W Bond committed
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

    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

598
    # no per-day limit because you can only rate listings you've exchanged
Daniel W Bond's avatar
Daniel W Bond committed
599
600
601
602
    @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
603
604
605
606
607

class EditRating(LoginRequiredMixin, UpdateView):
    model = Rating
    template_name = 'rating_edit.html'
    context_object_name = 'rating'
Daniel W Bond's avatar
Daniel W Bond committed
608
    # form_class = EditListingForm
Daniel W Bond's avatar
Daniel W Bond committed
609
610
611
612
613
614
615
616
    login_url = 'login'

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

    template_suffix_name = '_edit'

    def get_success_url(self):
        return reverse('ratings',
617
                       kwargs={'slug': self.object.listing.poster.slug})
Daniel W Bond's avatar
Daniel W Bond committed
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

    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