views.py 13.1 KB
Newer Older
Christophe Siraut's avatar
Christophe Siraut committed
1
from django.conf import settings
2 3 4
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
christophe siraut's avatar
christophe siraut committed
5 6
from django.core.urlresolvers import reverse
from django.forms.models import inlineformset_factory, BaseInlineFormSet
Christophe Siraut's avatar
Christophe Siraut committed
7
from django.shortcuts import get_object_or_404, render, HttpResponseRedirect
8
from django.template import RequestContext
9
from django.utils.translation import ugettext_lazy as _
Christophe Siraut's avatar
Christophe Siraut committed
10 11
from .forms import UserProfileForm, PollForm, ChoiceForm, VoteForm, BulletinForm
from .models import Poll, Choice, Vote, Bulletin
12
from datetime import timedelta
Christophe Siraut's avatar
Christophe Siraut committed
13 14 15 16 17 18 19 20 21 22 23 24 25

def email_notify(poll, voter):
    """Send email notification"""
    subject = _("Nuages email notification")
    message = _("User %s has voted.") % voter
    message += "\n\n"
    message += _("The link to your poll: %s") % poll.link
    message += "\n\n"
    message += _("Current results:")
    message += "\n\n"
    for choice in poll.choice_set.all():
        message += "%s: %i\n" % (choice.choice, choice.votecount)
    poll.user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
christophe siraut's avatar
christophe siraut committed
26

27

christophe siraut's avatar
christophe siraut committed
28
def new(request):
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
29
    if request.method == 'POST':
30
        form = PollForm(request.POST)
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
31
        if form.is_valid():
32 33 34 35 36
            poll = Poll(**form.cleaned_data)
            if request.user.is_authenticated():
                poll.user = request.user
            poll.save()
            key = 'is_' + poll.id + '_author'
37 38 39
            request.session[key] = True  # This writes cookie
            return HttpResponseRedirect(reverse('choices',
                                                args=(str(poll.id),)))
christophe siraut's avatar
christophe siraut committed
40
    else:
41
        form = PollForm()
42
        if request.user.is_anonymous():
43
            request.session.clear()
44 45
            messages.warning(request, _('You are not logged so you will not \
be able to modify your poll after creation or recieve notifications.'))
Christophe Siraut's avatar
Christophe Siraut committed
46 47 48
    return render(request,
                  'meetingpoll/poll_form.html',
                  {'form': form})
49

christophe siraut's avatar
christophe siraut committed
50

Christophe Siraut's avatar
Christophe Siraut committed
51
def get_formset(form, formset=BaseInlineFormSet, **kwargs):
christophe siraut's avatar
christophe siraut committed
52 53
    return inlineformset_factory(Poll, Choice, form, formset, **kwargs)

54

christophe siraut's avatar
christophe siraut committed
55 56
def editchoices(request, poll_id):

Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
57
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
58 59 60
    key = 'is_' + poll_id + '_author'  # Anonymous wants to edit his new poll?
    if request.user != poll.user and not request.session.get(key, False):
        return HttpResponseRedirect(reverse('home'))
christophe siraut's avatar
christophe siraut committed
61

Christophe Siraut's avatar
Christophe Siraut committed
62
    choiceFormset = get_formset(ChoiceForm, extra=1, can_delete=True)
christophe siraut's avatar
christophe siraut committed
63 64

    if request.method == "POST":
Christophe Siraut's avatar
Christophe Siraut committed
65 66 67 68 69
        formset = choiceFormset(request.POST, instance=poll)
        if formset.is_valid():
            formset.save()
            if not '_addanother' in request.POST:
                return HttpResponseRedirect(poll.link)
christophe siraut's avatar
christophe siraut committed
70
        else:
Christophe Siraut's avatar
Christophe Siraut committed
71 72
            messages.error(request,
                           _("There are some errors in the form you posted."))
73

Christophe Siraut's avatar
Christophe Siraut committed
74
    if Choice.objects.filter(poll=poll_id).count() == 0:
75 76 77 78 79 80
        choiceFormset = get_formset(ChoiceForm, extra=1, can_delete=True)
        formset = choiceFormset(instance=poll)
    else:
        last_choice = poll.choice_set.all().latest('choice').choice
        proposal = last_choice + timedelta(days=1)
        formset = choiceFormset(instance=poll, initial=[{'choice': proposal}])
81

Christophe Siraut's avatar
Christophe Siraut committed
82 83 84
    return render(request,
                  'meetingpoll/choice_form.html',
                  {'object': poll, 'formset': formset})
85

christophe siraut's avatar
christophe siraut committed
86

87 88 89
@login_required
def delete(request, poll_id):

Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
90
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
91

92
    if poll.user == request.user:
93 94 95 96 97
        poll.delete()

    return HttpResponseRedirect('/')


christophe siraut's avatar
christophe siraut committed
98
def make_buletin_form(poll, **kwargs):
99
    return [[VoteForm(prefix=choice)] for choice in Choice.objects.filter(poll=poll.id)]
christophe siraut's avatar
christophe siraut committed
100 101 102


def vote(request, poll_id):
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
103
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
104
    has_voted, is_updated = False, False
christophe siraut's avatar
christophe siraut committed
105 106

    if request.method == 'POST':
107

108 109
        form = BulletinForm(request.POST, initial={'poll': poll.id})
        vforms = [[VoteForm(request.POST, prefix=choice, instance=choice) ] for choice in Choice.objects.filter(poll=poll.id)]
christophe siraut's avatar
christophe siraut committed
110

111
        if form.is_valid():
112 113 114 115 116 117

            if request.POST.get('trap', False):
                return render(request,
                    'meetingpoll/poll_detail.html',
                    {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})

christophe siraut's avatar
christophe siraut committed
118 119 120 121 122 123 124
            if request.user.is_authenticated():
                voter = str(request.user)
            else:
                voter = form.cleaned_data['voter']
                if request.session.get('name'):
                    voter = request.session.get('name')

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
            for forms in vforms:
                for vorm in forms:
                    if vorm.is_valid():
                        comment = vorm.cleaned_data['comment']
                        if 'http' in comment or 'href' in comment:
                            messages.error(request, _('Sorry no link is allowed in comments.'))
                            return render(request,
                                'meetingpoll/poll_detail.html',
                                {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})

            if len(Bulletin.objects.filter(poll=poll.id)) > 100:
                messages.error(request, _('Sorry this poll reached the maximum of participants'))
                return render(request,
                    'meetingpoll/poll_detail.html',
                    {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})

christophe siraut's avatar
christophe siraut committed
141
            if voter != 'your name':
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
142 143
                if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                    bulletin = Bulletin(poll=poll, voter=voter)
christophe siraut's avatar
christophe siraut committed
144 145
                    bulletin.save()
                else:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
146
                    bulletin = Bulletin.objects.get(poll=poll.id, voter=voter)
christophe siraut's avatar
christophe siraut committed
147 148 149 150 151

                for forms in vforms:
                    for vorm in forms:
                        if vorm.is_valid():
                            try:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
152
                                choice = Choice.objects.get(choice=vorm.cleaned_data['choice'], poll=poll)
christophe siraut's avatar
christophe siraut committed
153
                            except:
Christophe Siraut's avatar
Christophe Siraut committed
154
                                return render(request, vorm.cleaned_data['choice'])
christophe siraut's avatar
christophe siraut committed
155

Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
156 157
                            if not Vote.objects.filter(choice=choice, bulletin=bulletin):
                                new = Vote(choice=choice, bulletin=bulletin, comment=vorm.cleaned_data['comment'])
Christophe Siraut's avatar
Christophe Siraut committed
158
                                if vorm.cleaned_data['voice']:
159 160 161
                                    new.voice = True
                                else:
                                    new.voice = False
christophe siraut's avatar
christophe siraut committed
162 163 164 165
                                new.save()
                                if new.voice:
                                    choice.votecount += 1
                                    choice.save()
166
                                if request.user.is_anonymous():  # Anonymous has voted...
christophe siraut's avatar
christophe siraut committed
167
                                    key = 'has_voted-' + poll.id
168 169
                                    request.session[key] = True  # This writes cookie
                                    request.session['name'] = voter  # This writes cookie
170
                                    has_voted = True  # Used to show "Forget me"
christophe siraut's avatar
christophe siraut committed
171
                            else:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
172
                                old = Vote.objects.get(choice=choice, bulletin=bulletin)
christophe siraut's avatar
christophe siraut committed
173 174 175 176 177 178 179 180 181 182 183 184 185

                                if old.voice:
                                    if not vorm.cleaned_data['voice']:
                                        choice.votecount -= 1
                                        choice.save()
                                else:
                                    if vorm.cleaned_data['voice']:
                                        choice.votecount += 1
                                        choice.save()

                                old.voice = vorm.cleaned_data['voice']
                                old.comment = vorm.cleaned_data['comment']
                                old.save()
186 187
                                is_updated = True
                if has_voted:
188
                    messages.success(request, _("Your vote has been counted, thank you."))
189
                if is_updated:
190
                    messages.success(request, _("Your vote has been updated, thank you."))
191 192 193 194 195 196
                if has_voted and poll.user:
                    try:
                        if poll.user.userprofile.email_notifications:
                            email_notify(poll, voter)
                    except:
                        pass
christophe siraut's avatar
christophe siraut committed
197
            else:
198
                messages.error(request, _('Did you forget to provide your name?'))
christophe siraut's avatar
christophe siraut committed
199
        else:
200
            messages.error(request, _('Did you forget to provide your name?'))
201
            voter = _('your name')
christophe siraut's avatar
christophe siraut committed
202 203 204 205 206 207 208 209 210

    else: # request.method = 'GET'

        key = 'is_' + poll.id + '_author'
        if request.session.get(key, False):
            # Assume author is positive for all choices, when he votes for the first time.
            vforms = [ [ VoteForm(initial={'choice': choice,'voice': True,}, prefix=choice) ] for choice in Choice.objects.filter(poll=poll_id) ]
        else:
            # Default formset for unknown user
211
            vforms = [ [ VoteForm(initial={'choice': choice,}, prefix=choice) ] for choice in Choice.objects.filter(poll=poll_id) ]
christophe siraut's avatar
christophe siraut committed
212 213 214 215
        if request.user.is_authenticated():
            voter = str(request.user)
            try:
                bulletin = Bulletin.objects.get(poll=poll,voter=voter)
216
                messages.info(request, _("You have voted."))
christophe siraut's avatar
christophe siraut committed
217 218 219 220 221 222 223
                diff = len(vforms) - len(Vote.objects.filter(bulletin=bulletin))
                if diff == 0:
                    """
                    Hum, previously bulletin has not the same amount of vote objects,
                    we should concatenate the existing votes with empty remaing ones...
                    Give an empty bulletin for now.
                    """
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
224
                    vforms = [ [ VoteForm(initial={'choice': vote.choice,'voice': vote.voice, 'comment': vote.comment}, prefix=vote.choice) ] for vote in Vote.objects.filter(bulletin=bulletin).order_by('choice__choice') ]
christophe siraut's avatar
christophe siraut committed
225 226 227 228

            except:
                pass
        else:
229 230 231 232 233
            voter = request.session.get('name')
            if voter:
                has_voted = True  # Used to show "Forget me"
            else:
                messages.info(request, _("Login let you modify your vote anytime."))
christophe siraut's avatar
christophe siraut committed
234 235 236 237
            key = 'has_voted-' + poll.id
            if request.session.get(key, False):
                #error_message = 'Modify your vote? (clear cookie if you are not ' + voter + ')'
                try:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
238
                    bulletin = Bulletin.objects.get(poll=poll, voter=voter)
239 240
                    messages.success(request, _('%s has voted and can still modify its vote.') % voter)
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
christophe siraut's avatar
christophe siraut committed
241 242 243 244 245 246 247
                    diff = len(vforms) - len(Vote.objects.filter(bulletin=bulletin))
                    if diff == 0:
                        """
                        Hum, previously bulletin has not the same amount of vote objects,
                        we should concatenate the existing votes with empty remaing ones...
                        Give an empty bulletin for now.
                        """
248
                        vforms = [ [ VoteForm(initial={'choice': vote.choice,'voice': vote.voice, 'comment': vote.comment,}, prefix=vote.choice) ] for vote in Vote.objects.filter(bulletin=bulletin).order_by('choice__choice') ]
christophe siraut's avatar
christophe siraut committed
249 250 251

                except:
                    pass
252 253 254
            else:
                if voter:
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
christophe siraut's avatar
christophe siraut committed
255

256
    form = BulletinForm(instance=poll, initial={'voter': voter})
Christophe Siraut's avatar
Christophe Siraut committed
257 258 259
    return render(request,
                  'meetingpoll/poll_detail.html',
                  {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})
260

christophe siraut's avatar
christophe siraut committed
261

chris's avatar
chris committed
262
def exp_csv(request, poll_id):
Christophe Siraut's avatar
Christophe Siraut committed
263 264 265 266 267 268
    import csv

    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = 'attachment; filename=nuages.csv'

Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
269
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
chris's avatar
chris committed
270 271
    choices = Choice.objects.filter(poll=poll)
    bulletins = Bulletin.objects.filter(poll=poll)
Christophe Siraut's avatar
Christophe Siraut committed
272 273 274
    writer = csv.writer(response, quotechar='"', quoting=csv.QUOTE_ALL)
    fr = ["",]
    for c in choices:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
275
        fr.append(c)
Christophe Siraut's avatar
Christophe Siraut committed
276 277 278 279 280 281 282
    writer.writerow(fr)
    for b in bulletins:
        r = [b.voter.encode("utf-8"),]
        for v in Vote.objects.filter(bulletin=b):
            r.append(v)
        writer.writerow(r)
    return response
283

Christophe Siraut's avatar
Christophe Siraut committed
284 285 286 287 288 289 290 291 292 293 294 295 296 297
@login_required
def profile(request):
    """profile view"""
    if request.method == 'POST':
        form = UserProfileForm(request.POST)
        if form.is_valid():
            for k, v in form.cleaned_data.iteritems():
                setattr(request.user.userprofile, k, v)
            request.user.userprofile.save()
            return HttpResponseRedirect(reverse('home'))
    form = UserProfileForm(instance=request.user.userprofile)
    return render(request, "form.html", {'form': form})


298 299 300
def clear_cookie(request, poll_id):
    request.session.clear()
    return HttpResponseRedirect(reverse('vote', args=(poll_id,)))