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