def wrapper(request, slug, **kwargs): tlk = get_object_or_404(models.Talk, slug=slug) if request.user.is_anonymous(): full_access = False elif request.user.is_staff: full_access = True else: try: tlk.get_all_speakers().get(user__id=request.user.id) except (models.Speaker.DoesNotExist, models.Speaker.MultipleObjectsReturned): # The MultipleObjectsReturned can happen if the user is not logged on and .id is None full_access = False else: full_access = True # if the talk is unconfirmed can access: # * superusers or speakers (full access = True) # * if the community voting is in progress who has the right to vote if tlk.status == 'proposed' and not full_access: conf = models.Conference.objects.current() if not settings.VOTING_OPENED(conf, request.user): return http.HttpResponseForbidden() if not settings.VOTING_ALLOWED(request.user): if settings.VOTING_DISALLOWED: return redirect(settings.VOTING_DISALLOWED) else: return http.HttpResponseForbidden() return f(request, slug, talk=tlk, full_access=full_access, **kwargs)
def wrapper(request, slug, **kwargs): try: profile = models.AttendeeProfile.objects\ .select_related('user')\ .get(slug=slug) except models.AttendeeProfile.DoesNotExist: raise http.Http404() if request.user.is_staff or request.user == profile.user: full_access = True else: full_access = False # if the profile belongs to a speaker with talk of "accepted" is visible # whatever you say the same profile. accepted = models.TalkSpeaker.objects\ .filter(speaker__user=profile.user)\ .filter(talk__status='accepted')\ .count() if not accepted: # if the community voting is open and the profile belongs to a speaker # with the talk in the race page is visible conf = models.Conference.objects.current() if not (settings.VOTING_OPENED(conf, request.user) and settings.VOTING_ALLOWED(request.user)): if profile.visibility == 'x': return http.HttpResponseForbidden() elif profile.visibility == 'm' and request.user.is_anonymous( ): return http.HttpResponseForbidden() return f(request, slug, profile=profile, full_access=full_access, **kwargs)
def wrapper(request, slug, **kwargs): spk = get_object_or_404(models.Speaker, slug=slug) if request.user.is_staff or request.user == spk.user: full_access = True talks = spk.talks() else: full_access = False conf = models.Conference.objects.current() if settings.VOTING_OPENED(conf, request.user): if settings.VOTING_ALLOWED(request.user): talks = spk.talks() else: if settings.VOTING_DISALLOWED: return redirect(settings.VOTING_DISALLOWED) else: raise http.Http404() else: talks = spk.talks(status='accepted') if talks.count() == 0: raise http.Http404() return f(request, slug, speaker=spk, talks=talks, full_access=full_access, **kwargs)
def wrapper(request, slug, **kwargs): try: profile = models.AttendeeProfile.objects\ .select_related('user')\ .get(slug=slug) except models.AttendeeProfile.DoesNotExist: raise http.Http404() if request.user.is_staff or request.user == profile.user: full_access = True else: full_access = False # se il profilo appartiene ad uno speaker con dei talk "accepted" è # visibile qualunque cosa dica il profilo stesso accepted = models.TalkSpeaker.objects\ .filter(speaker__user=profile.user)\ .filter(talk__status='accepted')\ .count() if not accepted: # Se la votazione comunitaria à aperta e il profilo appartiene # ad uno speaker con dei talk in gara la pagina è visibile conf = models.Conference.objects.current() if not (settings.VOTING_OPENED(conf, request.user) and settings.VOTING_ALLOWED(request.user)): if profile.visibility == 'x': return http.HttpResponseForbidden() elif profile.visibility == 'm' and request.user.is_anonymous( ): return http.HttpResponseForbidden() return f(request, slug, profile=profile, full_access=full_access, **kwargs)
def wrapper(request, slug, **kwargs): tlk = get_object_or_404(models.Talk, slug=slug) if request.user.is_anonymous(): full_access = False elif request.user.is_staff: full_access = True else: try: tlk.get_all_speakers().get(user__id=request.user.id) except (models.Speaker.DoesNotExist, models.Speaker.MultipleObjectsReturned): # Il MultipleObjectsReturned può capitare se l'utente non è loggato # e .id vale None full_access = False else: full_access = True # Se il talk non è confermato possono accedere: # * i super user o gli speaker (full_access = True) # * se la votazione comunitarià è in corso chi ha il diritto di votare if tlk.status == 'proposed' and not full_access: conf = models.Conference.objects.current() if not settings.VOTING_OPENED(conf, request.user): return http.HttpResponseForbidden() if not settings.VOTING_ALLOWED(request.user): if settings.VOTING_DISALLOWED: return redirect(settings.VOTING_DISALLOWED) else: return http.HttpResponseForbidden() return f(request, slug, talk=tlk, full_access=full_access, **kwargs)
def subcommunity_talk_voting(request): """ View Callback used for community talk voting. This view wraps the conference voting view, and adds a talk filter based on sub_communities. """ if request.method == 'POST': return voting(request) else: conf, talks, voting_allowed = get_data_for_context(request) if not csettings.VOTING_OPENED(conf, request.user): if csettings.VOTING_CLOSED: return redirect(csettings.VOTING_CLOSED) else: raise http.Http404() ctx = filter_talks_in_context(request, talks, voting_allowed) filtered_talks = ctx['talks'] sub_community_choices = [list(v) for v in TALK_SUBCOMMUNITY] sub_community_choices[0][1] = _('All') class SubCommunityOptionForm(OptionForm): sub_community = forms.ChoiceField( choices=sub_community_choices, required=False, initial='', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) if request.GET: form = SubCommunityOptionForm(data=request.GET) form.is_valid() options = form.cleaned_data else: form = SubCommunityOptionForm() options = { 'abstracts': 'not-voted', 'talk_type': '', 'language': '', 'tags': '', 'order': 'vote', 'sub_community': '', } if options['sub_community'] != '': sub_community_talks = P3Talk.objects.filter( sub_community=options['sub_community']) sub_community_talks = [p3talk.pk for p3talk in sub_community_talks] talks_id = [t['id'] for t in filtered_talks] talks = list() for idx, tid in enumerate(talks_id): if tid in sub_community_talks: talks.append(filtered_talks[idx]) ctx.update({'talks': talks}) ctx.update({'form': form}) if request.is_ajax(): tpl = 'conference/ajax/voting.html' else: tpl = 'conference/voting.html' return render(request, tpl, ctx)
def voting(request): conf, talks, voting_allowed = get_data_for_context(request) if not settings.VOTING_OPENED(conf, request.user): if settings.VOTING_CLOSED: return redirect(settings.VOTING_CLOSED) else: raise http.Http404() if request.method == 'POST': if not voting_allowed: return http.HttpResponseBadRequest('anonymous user not allowed') data = dict((x.id, x) for x in talks) for k, v in filter(lambda x: x[0].startswith('vote-'), request.POST.items()): try: talk = data[int(k[5:])] except KeyError: return http.HttpResponseBadRequest('invalid talk') except ValueError: return http.HttpResponseBadRequest('id malformed') if not v: models.VotoTalk.objects.filter(user=request.user, talk=talk).delete() else: try: vote = Decimal(v) except ValueError: return http.HttpResponseBadRequest('vote malformed') try: o = models.VotoTalk.objects.get(user=request.user, talk=talk) except models.VotoTalk.DoesNotExist: o = models.VotoTalk(user=request.user, talk=talk) if not vote: if o.id: o.delete() else: o.vote = vote o.save() if request.is_ajax(): return http.HttpResponse('') else: return HttpResponseRedirectSeeOther( reverse('conference-voting') + '?' + request.GET.urlencode()) else: from conference.forms import TagField, ReadonlyTagWidget, PseudoRadioRenderer class OptionForm(forms.Form): abstracts = forms.ChoiceField( choices=( ('not-voted', 'Not yet voted'), ('all', 'All'), ), required=False, initial='not-voted', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) talk_type = forms.ChoiceField( label=u'Session type', choices=(('all', 'All'), ) + tuple(settings.TALK_TYPES_TO_BE_VOTED), required=False, initial='all', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) language = forms.ChoiceField( choices=(('all', 'All'), ) + tuple(settings.TALK_SUBMISSION_LANGUAGES), required=False, initial='all', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) order = forms.ChoiceField( choices=( ('random', 'Random order'), ('vote', 'Vote'), ('speaker', 'Speaker name'), ), required=False, initial='random', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) tags = TagField( required=False, widget=ReadonlyTagWidget(), ) # I want to associate with each talk a "unique" number to display next to the title to be able to easily find. ordinal = dict() for ix, t in enumerate( talks.order_by('created').values_list('id', flat=True)): ordinal[t] = ix user_votes = models.VotoTalk.objects.filter(user=request.user.id) # Start by sorting talks by name talks = talks.order_by('speakers__user__first_name', 'speakers__user__last_name') if request.GET: form = OptionForm(data=request.GET) form.is_valid() options = form.cleaned_data else: form = OptionForm() options = { 'abstracts': 'not-voted', 'talk_type': 'all', 'language': 'all', 'tags': '', 'order': 'random', } # if options['abstracts'] == 'not-voted': # talks = talks.exclude(id__in=user_votes.values('talk_id')) if options['talk_type'] in ( tchar for (tchar, tdef) in settings.TALK_TYPES_TO_BE_VOTED): talks = talks.filter(type__startswith=options['talk_type']) if options['language'] in ( lcode for (lcode, ldef) in settings.TALK_SUBMISSION_LANGUAGES): talks = talks.filter(language=options['language']) if options['tags']: # if options['tags'] ends us a tag not associated with any talk I results # in a query that results from scratch; to avoid this limit the usable tag # as a filter to those associated with talk. allowed = set() ctt = ContentType.objects.get_for_model(models.Talk) for t, usage in dataaccess.tags().items(): for cid, oid in usage: if cid == ctt.id: allowed.add(t.name) break tags = set(options['tags']) & allowed if tags: talks = talks.filter(id__in=models.ConferenceTaggedItem.objects\ .filter( content_type__app_label='conference', content_type__model='talk', tag__name__in=tags)\ .values('object_id') ) talk_order = options['order'] votes = dict((x.talk_id, x) for x in user_votes) # As talks are sorted by a model connected via a m2m can I have repeated the talk, and # distinct does not apply in these case. # # It can only filtered in python, at this point I take this opportunity to engage # votes user using a single loop. dups = set() def filter_vote(t): if t['id'] in dups: return False dups.add(t['id']) t['user_vote'] = votes.get(t['id']) t['ordinal'] = ordinal[t['id']] return True talks = filter(filter_vote, talks.values('id')) # Fix talk order, if necessary if talk_order == 'vote': def key(x): if x['user_vote']: return x['user_vote'].vote else: return Decimal('-99.99') talks = reversed(sorted(reversed(talks), key=key)) elif talk_order == 'random': random.shuffle(talks) elif talk_order == 'speaker': # Already sorted pass ctx = { 'voting_allowed': voting_allowed, 'talks': list(talks), 'form': form, } if request.is_ajax(): tpl = 'conference/ajax/voting.html' else: tpl = 'conference/voting.html' return render(request, tpl, ctx)
def voting(request): conf, talks, voting_allowed = get_data_for_context(request) if not settings.VOTING_OPENED(conf, request.user): if settings.VOTING_CLOSED: return redirect(settings.VOTING_CLOSED) else: raise http.Http404() if request.method == 'POST': if not voting_allowed: return http.HttpResponseBadRequest('anonymous user not allowed') data = dict((x.id, x) for x in talks) for k, v in filter(lambda x: x[0].startswith('vote-'), request.POST.items()): try: talk = data[int(k[5:])] except KeyError: return http.HttpResponseBadRequest('invalid talk') except ValueError: return http.HttpResponseBadRequest('id malformed') if not v: models.VotoTalk.objects.filter(user=request.user, talk=talk).delete() else: try: vote = Decimal(v) except ValueError: return http.HttpResponseBadRequest('vote malformed') try: o = models.VotoTalk.objects.get(user=request.user, talk=talk) except models.VotoTalk.DoesNotExist: o = models.VotoTalk(user=request.user, talk=talk) if not vote: if o.id: o.delete() else: o.vote = vote o.save() if request.is_ajax(): return http.HttpResponse('') else: return HttpResponseRedirectSeeOther( reverse('conference-voting') + '?' + request.GET.urlencode()) else: from conference.forms import TagField, ReadonlyTagWidget, PseudoRadioRenderer class OptionForm(forms.Form): abstracts = forms.ChoiceField( choices=( ('not-voted', 'To be voted'), ('all', 'All'), ), required=False, initial='not-voted', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) talk_type = forms.ChoiceField( choices=settings.TALK_TYPES_TO_BE_VOTED, required=False, initial='all', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) language = forms.ChoiceField( choices=( ('all', 'All'), ('en', 'English'), ('it', 'Italian'), ), required=False, initial='all', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) order = forms.ChoiceField( choices=( ('vote', 'Vote'), ('speaker', 'Speaker name'), ), required=False, initial='vote', widget=forms.RadioSelect(renderer=PseudoRadioRenderer), ) tags = TagField( required=False, widget=ReadonlyTagWidget(), ) # voglio poter associare ad ogni talk un numero "univoco" da mostrare # accanto al titolo per poterlo individuare facilmente. ordinal = dict() for ix, t in enumerate( talks.order_by('created').values_list('id', flat=True)): ordinal[t] = ix user_votes = models.VotoTalk.objects.filter(user=request.user.id) talks = talks.order_by('speakers__user__first_name', 'speakers__user__last_name') if request.GET: form = OptionForm(data=request.GET) form.is_valid() options = form.cleaned_data else: form = OptionForm() options = { 'abstracts': 'not-voted', 'talk_type': '', 'language': '', 'tags': '', 'order': 'vote', } if options['abstracts'] != 'all': talks = talks.exclude(id__in=user_votes.values('talk_id')) if options['talk_type'] in ('s', 't', 'p'): talks = talks.filter(type=options['talk_type']) if options['language'] in ('en', 'it'): talks = talks.filter(language=options['language']) if options['tags']: # se in options['tags'] ci finisce un tag non associato ad alcun # talk ho come risultato una query che da zero risultati; per # evitare questo limito i tag usabili come filtro a quelli # associati ai talk. allowed = set() ctt = ContentType.objects.get_for_model(models.Talk) for t, usage in dataaccess.tags().items(): for cid, oid in usage: if cid == ctt.id: allowed.add(t.name) break tags = set(options['tags']) & allowed if tags: talks = talks.filter(id__in=models.ConferenceTaggedItem.objects\ .filter( content_type__app_label='conference', content_type__model='talk', tag__name__in=tags)\ .values('object_id') ) talk_order = options['order'] votes = dict((x.talk_id, x) for x in user_votes) # Poichè talks è ordinato per un modello collegato tramite una # ManyToMany posso avere dei talk ripetuti, e il distinct non si # applica in questi casi. # # Non mi rimane che filtrare in python, a questo punto ne approfitto # per agganciare i voti dell'utente utilizzando un unico loop. dups = set() def filter_vote(t): if t['id'] in dups: return False dups.add(t['id']) t['user_vote'] = votes.get(t['id']) t['ordinal'] = ordinal[t['id']] return True talks = filter(filter_vote, talks.values('id')) if talk_order != 'speaker': def key(x): if x['user_vote']: return x['user_vote'].vote else: return Decimal('-99.99') talks = reversed(sorted(reversed(talks), key=key)) ctx = { 'voting_allowed': voting_allowed, 'talks': list(talks), 'form': form, } if request.is_ajax(): tpl = 'conference/ajax/voting.html' else: tpl = 'conference/voting.html' return render(request, tpl, ctx)