views.py 22.4 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, SuperuserRequiredMixin
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
175
176
177
178
179
180
181
182
class DeleteListing(LoginRequiredMixin, SuperuserRequiredMixin, DeleteView):
    model = Listing
    context_object_name = 'listing'
    template_name = 'delete_listing.html'
    login_url = 'login'

    def get_success_url(self):
        return reverse('mod')


183
184
class CreateBid(CreateView):
    model = Bid
Daniel W Bond's avatar
Daniel W Bond committed
185
    fields = ['listing', 'price', 'text', ]
186
    context_object_name = 'bid'
187
    template_name = 'detail_listing.html'
188

189
190
191
192
193
194
    def form_valid(self, form):
        me = Student.objects.get(user=self.request.user)

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

195
    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
196
197
198
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})

199

200
201
# ...to make this single view
class ListingPage(LoginRequiredMixin, View):
202
    login_url = 'login'
203
204
205
206
207
208
209
210

    # 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
211
212
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
    # rate limit is higher for bids
213
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
214
215
216
217
    def post(self, request, *args, **kwargs):
        view = CreateBid.as_view()
        return view(request, *args, **kwargs)

218

Daniel W Bond's avatar
Daniel W Bond committed
219
# and we return to our regularly schedule programming
220
221
class CreateFlag(LoginRequiredMixin, CreateView):
    model = Flag
Daniel W Bond's avatar
Daniel W Bond committed
222
    fields = ['reason', ]
223
    template_name = 'create_flag.html'
224
    context_object_name = 'flag'
225
    login_url = 'login'
226

227
228
229
230
231
232
233
234
235
236
237
238
    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)

239
    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
240
241
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})
242
243
244
245
246

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

247
        # duplicated code!!!
248
249
250
251
252
        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)

253
        posting_student = selected_listing.poster
254
255

        # you can't flag your own listing
256
        if (posting_student == me):
257
            return HttpResponseForbidden()
258
259
260

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

        context['listing'] = selected_listing
265
266
267

        form = FlagForm()
        context['my_form'] = form
268
269
        return context

Daniel W Bond's avatar
Daniel W Bond committed
270
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
271
    @ratelimit(key='user', rate='100/d', method='POST', block=True)
Daniel W Bond's avatar
Daniel W Bond committed
272
273
274
    def post(self, request, *args, **kwargs):
        return super(CreateFlag, self).post(request, *args, **kwargs)

Daniel W Bond's avatar
Daniel W Bond committed
275

276
277
class DeleteFlag(LoginRequiredMixin, DeleteView):
    model = Flag
278
    context_object_name = 'flag'
279
    template_name = 'delete_flag.html'
280
    login_url = 'login'
281
282

    def get_success_url(self):
Daniel W Bond's avatar
Daniel W Bond committed
283
284
        return reverse('detail_listing',
                       kwargs={'slug': self.object.listing.slug})
285
286
287
288
289

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

290
        flag_student = self.get_object().flagger
291

292
293
294
        # if you didn't create the flag, you can't delete the flag
        if not(me == flag_student):
            return HttpResponseForbidden()
295
296
297

        return context

Daniel W Bond's avatar
Daniel W Bond committed
298

299
# not implemented -- tbd
300
301
302
303
304
305
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
306

Daniel W Bond's avatar
Daniel W Bond committed
307
class EditBid(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
308
    model = Bid
Daniel W Bond's avatar
Daniel W Bond committed
309
310
    template_name = 'bid_edit.html'
    context_object_name = 'bid'
Daniel W Bond's avatar
Daniel W Bond committed
311
    # form_class = EditBidForm
Daniel W Bond's avatar
Daniel W Bond committed
312
313
    login_url = 'login'

314
    form_valid_message = "Your bid was successfully updated!"
Daniel W Bond's avatar
Daniel W Bond committed
315
316
317
318
319

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

    def get_success_url(self):
        return reverse('detail_listing',
Daniel W Bond's avatar
Daniel W Bond committed
320
                       kwargs={'slug': self.object.listing.slug})
Daniel W Bond's avatar
Daniel W Bond committed
321
322
323
324
325
326
327
328
329
330
331

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

332
333
        # 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
334
335
336
            raise Http404

        return context
337

Daniel W Bond's avatar
Daniel W Bond committed
338

339
class EditListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
Daniel W Bond's avatar
Daniel W Bond committed
340
    model = Listing
341
342
    template_name = 'listing_edit.html'
    context_object_name = 'listing'
Daniel W Bond's avatar
Daniel W Bond committed
343
    # form_class = EditListingForm
344
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
345

346
    form_valid_message = "Your listing was successfully updated!"
347

Daniel W Bond's avatar
Daniel W Bond committed
348
349
    fields = ['title', 'author', 'isbn', 'year', 'edition', 'condition',
              'access_code', 'description', 'price', 'photo', ]
350
351
352
353

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

354
        me = Student.objects.get(user=self.request.user)
355
        posting_student = self.get_object().poster
356

357
        if not(posting_student == me):
358
            return HttpResponseForbidden()
359

Daniel W Bond's avatar
Daniel W Bond committed
360
361
        return context

362

363
class ExchangeListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
364
    model = Listing
Daniel W Bond's avatar
Daniel W Bond committed
365
    fields = ['email_message', 'winning_bid', ]
366
    context_object_name = 'listing'
367
    template_name = 'listing_exchange.html'
368
    login_url = 'login'
369

370
    form_valid_message = "Your email was successfully sent!"
371

372
    def form_valid(self, form):
373
        # filling out fields
374
        today = date.today()
375
        self.obj = self.get_object()
376

377
        form.instance.exchanged = True
378
        form.instance.date_closed = today
379
380

        # sending email
Daniel W Bond's avatar
Daniel W Bond committed
381
        # I'm still second guessing as to whether this should be in this method
382
383
        text_email = get_template('email/exchanged.txt')
        html_email = get_template('email/exchanged.html')
384

Daniel W Bond's avatar
Daniel W Bond committed
385
386
        email_context = Context({
            'bidder_first_name': form.instance.winning_bid.bidder.user.first_name,
387
            'poster_name': self.obj.poster.user.get_full_name(),
Daniel W Bond's avatar
Daniel W Bond committed
388
389
            'bid_num': form.instance.winning_bid.price,
            'listing_title': self.obj.title,
390
            'poster_email': self.obj.poster.user.email,
Daniel W Bond's avatar
Daniel W Bond committed
391
            'email_message': form.instance.email_message, })
392

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

406
407
408
        self.obj.poster.emails_sent += 2
        self.obj.poster.save()

409
        return super(ExchangeListing, self).form_valid(form)
410

411
    def get_context_data(self, **kwargs):
412
        context = super(ExchangeListing, self).get_context_data(**kwargs)
413

414
        me = Student.objects.get(user=self.request.user)
415
        posting_student = self.get_object().poster
416

417
        if not(posting_student == me):
418
            return HttpResponseForbidden()
419

420
421
        bid_count = Bid.objects.filter(listing=self.get_object).count()
        if bid_count < 1:
422
            # because the page shouldn't exist in this scenario
Daniel W Bond's avatar
Daniel W Bond committed
423
424
            raise Http404

425
        form = ExchangeListingForm()
426
427
428
429
        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
430
431
        return context

Daniel W Bond's avatar
Daniel W Bond committed
432
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
433
    @ratelimit(key='user', rate='50/d', method='POST', block=True)
Daniel W Bond's avatar
Daniel W Bond committed
434
    def post(self, request, *args, **kwargs):
435
        return super(ExchangeListing, self).post(request, *args, **kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
436

437

438
class UnExchangeListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
439
    model = Listing
440
    fields = ['email_message', ]
441
    context_object_name = 'listing'
442
    template_name = 'listing_unexchange.html'
443
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
444

445
    form_valid_message = """Your exchange has been successfully cancelled,
446
                     and your email successfully sent!"""
447

448
    def form_valid(self, form):
449
        self.obj = self.get_object()
450
451
        text_email = get_template('email/unexchanged.txt')
        html_email = get_template('email/unexchanged.html')
452
453
454

        email_context = Context({
            'bidder_first_name': self.obj.winning_bid.bidder.user.first_name,
455
            'poster_name': self.obj.poster.user.get_full_name(),
456
457
            'bid_num': self.obj.winning_bid.price,
            'listing_title': self.obj.title,
458
459
            'poster_email': self.obj.poster.user.email,
            'poster_email': form.instance.email_message, })
460
461
462

        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
463
                                       # self.obj.winning_bid.bidder.user.email,
464
                                       # self.obj.poster.user.email)
465
466
467
468
469
470
471
472
473
                                       '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()

474
475
476
        self.obj.poster.emails_sent += 2
        self.obj.poster.save()

477
        # this has to come after the email has been sent, otherwise these are
Daniel W Bond's avatar
Daniel W Bond committed
478
        # cleaned out
479
        form.instance.exchanged = False
480
481
        form.instance.date_closed = None
        form.instance.winning_bid = None
482

483
        return super(UnExchangeListing, self).form_valid(form)
484

Daniel W Bond's avatar
Daniel W Bond committed
485
    def get_context_data(self, **kwargs):
486
        context = super(UnExchangeListing, self).get_context_data(**kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
487

488
        me = Student.objects.get(user=self.request.user)
489
        posting_student = self.get_object().poster
Daniel W Bond's avatar
Daniel W Bond committed
490

491
        if not(posting_student == me):
492
            return HttpResponseForbidden()
Daniel W Bond's avatar
Daniel W Bond committed
493

494
        form = UnExchangeListingForm()
495
496
        context['my_form'] = form

Daniel W Bond's avatar
Daniel W Bond committed
497
        return context
Daniel W Bond's avatar
Daniel W Bond committed
498

Daniel W Bond's avatar
Daniel W Bond committed
499
    @ratelimit(key='user', rate='5/m', method='POST', block=True)
500
    @ratelimit(key='user', rate='50/d', method='POST', block=True)
Daniel W Bond's avatar
Daniel W Bond committed
501
    def post(self, request, *args, **kwargs):
502
        return super(UnExchangeListing, self).post(request, *args, **kwargs)
503

Daniel W Bond's avatar
Daniel W Bond committed
504

505
class CancelListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
Daniel W Bond's avatar
Daniel W Bond committed
506
    model = Listing
507
    fields = []
508
    template_suffix_name = '_cancel'
509
510
    context_object_name = 'listing'
    template_name = 'listing_cancel.html'
511
    login_url = 'login'
Daniel W Bond's avatar
Daniel W Bond committed
512

513
514
    form_valid_message = "Your listing was successfully cancelled!"

515
516
517
518
519
520
521
    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
522
    def get_context_data(self, **kwargs):
523
        context = super(CancelListing, self).get_context_data(**kwargs)
Daniel W Bond's avatar
Daniel W Bond committed
524

525
        me = Student.objects.get(user=self.request.user)
526
        posting_student = self.get_object().poster
Daniel W Bond's avatar
Daniel W Bond committed
527

528
        if not(posting_student == me):
529
            return HttpResponseForbidden()
Daniel W Bond's avatar
Daniel W Bond committed
530

Daniel W Bond's avatar
Daniel W Bond committed
531
        return context
532

Daniel W Bond's avatar
Daniel W Bond committed
533

534
class ReopenListing(LoginRequiredMixin, FormValidMessageMixin, UpdateView):
535
    model = Listing
536
    fields = []
537
    template_suffix_name = '_reopen'
538
539
    context_object_name = 'listing'
    template_name = 'listing_reopen.html'
540
    login_url = 'login'
541

542
    form_valid_message = "Your listing was successfully reopened!"
543

544
545
546
547
548
    def form_valid(self, form):
        form.instance.cancelled = False
        form.instance.date_closed = None
        return super(ReopenListing, self).form_valid(form)

549
550
551
    def get_context_data(self, **kwargs):
        context = super(ReopenListing, self).get_context_data(**kwargs)

552
        me = Student.objects.get(user=self.request.user)
553
        posting_student = self.get_object().poster
554

555
        if not(posting_student == me):
556
            return HttpResponseForbidden()
557

Daniel W Bond's avatar
Daniel W Bond committed
558
        return context
Daniel W Bond's avatar
Daniel W Bond committed
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581


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',
582
                       kwargs={'slug': self.object.listing.poster.slug})
Daniel W Bond's avatar
Daniel W Bond committed
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610

    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

611
    # no per-day limit because you can only rate listings you've exchanged
Daniel W Bond's avatar
Daniel W Bond committed
612
613
614
615
    @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
616
617
618
619
620

class EditRating(LoginRequiredMixin, UpdateView):
    model = Rating
    template_name = 'rating_edit.html'
    context_object_name = 'rating'
Daniel W Bond's avatar
Daniel W Bond committed
621
    # form_class = EditListingForm
Daniel W Bond's avatar
Daniel W Bond committed
622
623
624
625
626
627
628
629
    login_url = 'login'

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

    template_suffix_name = '_edit'

    def get_success_url(self):
        return reverse('ratings',
630
                       kwargs={'slug': self.object.listing.poster.slug})
Daniel W Bond's avatar
Daniel W Bond committed
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663

    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