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

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)
chris's avatar
chris committed
25

26

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

chris's avatar
chris committed
49

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

53

chris's avatar
chris committed
54 55
def editchoices(request, poll_id):

Christophe Siraut's avatar
Christophe Siraut committed
56
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
57 58 59
    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'))
chris's avatar
chris committed
60

Christophe Siraut's avatar
Christophe Siraut committed
61
    choiceFormset = get_formset(ChoiceForm, extra=1, can_delete=True)
chris's avatar
chris committed
62 63

    if request.method == "POST":
Christophe Siraut's avatar
Christophe Siraut committed
64 65 66 67
        formset = choiceFormset(request.POST, instance=poll)
        if formset.is_valid():
            formset.save()
            if not '_addanother' in request.POST:
chris's avatar
chris committed
68 69

                voter = get_voter_name(request)
70
                if voter and not Bulletin.objects.filter(poll=poll.id, voter=voter):
chris's avatar
chris committed
71 72 73 74 75 76
                    bulletin = Bulletin(poll=poll, voter=voter)
                    bulletin.save()
                    votes = [Vote(bulletin=bulletin, choice=choice, voice=True)
                             for choice in Choice.objects.filter(poll=poll.id)]
                    for v in votes:
                        v.save()
77 78 79 80
                    if request.user.is_anonymous():  # Anonymous has voted...
                        key = 'has_voted-' + poll.id
                        request.session[key] = True  # This writes cookie
                        request.session['name'] = voter  # This writes cookie
chris's avatar
chris committed
81
                poll.save()
chris's avatar
chris committed
82

chris's avatar
chris committed
83
                return HttpResponseRedirect(reverse('meetingpoll', args=(str(poll.id),)))
chris's avatar
chris committed
84
        else:
Christophe Siraut's avatar
Christophe Siraut committed
85 86
            messages.error(request,
                           _("There are some errors in the form you posted."))
87

Christophe Siraut's avatar
Christophe Siraut committed
88
    if Choice.objects.filter(poll=poll_id).count() == 0:
89 90 91 92 93 94
        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}])
95

Christophe Siraut's avatar
Christophe Siraut committed
96 97 98
    return render(request,
                  'meetingpoll/choice_form.html',
                  {'object': poll, 'formset': formset})
99

chris's avatar
chris committed
100

101 102 103
@login_required
def delete(request, poll_id):

Christophe Siraut's avatar
Christophe Siraut committed
104
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
105

106
    if poll.user == request.user:
107 108 109 110 111
        poll.delete()

    return HttpResponseRedirect('/')


chris's avatar
chris committed
112
def make_buletin_form(poll, **kwargs):
113
    return [[VoteForm(prefix=choice)] for choice in Choice.objects.filter(poll=poll.id)]
chris's avatar
chris committed
114 115


chris's avatar
chris committed
116 117 118 119 120 121 122 123 124
def get_voter_name(request, form=None):
    if request.user.is_authenticated():
        return str(request.user)
    else:
        if form:
            return form.cleaned_data['voter']
        if request.session.get('name'):
            return request.session.get('name')

chris's avatar
chris committed
125
def vote(request, poll_id):
Christophe Siraut's avatar
Christophe Siraut committed
126
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
127
    has_voted, is_updated = False, False
chris's avatar
chris committed
128 129

    if request.method == 'POST':
130

131
        form = BulletinForm(request.POST, initial={'poll': poll.id})
chris's avatar
chris committed
132 133
        vforms = [[VoteForm(request.POST, prefix=choice, instance=choice)]
                  for choice in Choice.objects.filter(poll=poll.id)]
chris's avatar
chris committed
134

135
        if form.is_valid():
136 137

            if request.POST.get('trap', False):
chris's avatar
chris committed
138 139
                return render(
                    request,
140
                    'meetingpoll/poll_detail.html',
chris's avatar
chris committed
141 142 143 144
                    {'object': poll,
                     'form': form,
                     'vforms': vforms,
                     'has_voted': has_voted})
145

chris's avatar
chris committed
146
            voter = get_voter_name(request, form)
chris's avatar
chris committed
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
            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})

chris's avatar
chris committed
164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
            if not voter or voter == 'your name':
                messages.error(request, _('Did you forget to provide your name?'))
                form = BulletinForm(instance=poll, initial={'voter': voter})
                return render(request,
                    'meetingpoll/poll_detail.html',
                    {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})

            if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                bulletin = Bulletin(poll=poll, voter=voter)
                bulletin.save()
            else:
                bulletin = Bulletin.objects.get(poll=poll.id, voter=voter)


            for forms in vforms:
                for vorm in forms:
                    if vorm.is_valid():
                        try:
                            choice = Choice.objects.get(choice=vorm.cleaned_data['choice'], poll=poll)
                        except:
chris's avatar
chris committed
184
                            continue
chris's avatar
chris committed
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

                        if not Vote.objects.filter(choice=choice, bulletin=bulletin):
                            new = Vote(choice=choice, bulletin=bulletin, comment=vorm.cleaned_data['comment'])
                            if vorm.cleaned_data['voice']:
                                new.voice = True
                            else:
                                new.voice = False
                            new.save()
                            if new.voice:
                                choice.votecount += 1
                                choice.save()
                            if request.user.is_anonymous():  # Anonymous has voted...
                                key = 'has_voted-' + poll.id
                                request.session[key] = True  # This writes cookie
                                request.session['name'] = voter  # This writes cookie
                                has_voted = True  # Used to show "Forget me"
                        else:
                            old = Vote.objects.get(choice=choice, bulletin=bulletin)

                            if old.voice:
                                if not vorm.cleaned_data['voice']:
                                    choice.votecount -= 1
                                    choice.save()
                            else:
chris's avatar
chris committed
209
                                if vorm.cleaned_data['voice']:
chris's avatar
chris committed
210 211
                                    choice.votecount += 1
                                    choice.save()
chris's avatar
chris committed
212 213 214 215 216 217 218 219 220 221 222 223

                            old.voice = vorm.cleaned_data['voice']
                            old.comment = vorm.cleaned_data['comment']
                            old.save()
                            is_updated = True

            if has_voted and poll.user:
                try:
                    if poll.user.userprofile.email_notifications:
                        email_notify(poll, voter)
                except:
                    pass
chris's avatar
chris committed
224 225 226 227 228 229

            if has_voted or is_updated:
                messages.success(request, _("Your vote has been counted, thank you."))
                poll.save()
                return HttpResponseRedirect(reverse('vote', args=(poll_id,)))

chris's avatar
chris committed
230
        else:
231
            messages.error(request, _('Did you forget to provide your name?'))
232
            voter = _('your name')
chris's avatar
chris committed
233 234 235 236 237 238 239 240 241

    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
242
            vforms = [ [ VoteForm(initial={'choice': choice,}, prefix=choice) ] for choice in Choice.objects.filter(poll=poll_id) ]
chris's avatar
chris committed
243 244 245 246
        if request.user.is_authenticated():
            voter = str(request.user)
            try:
                bulletin = Bulletin.objects.get(poll=poll,voter=voter)
247
                messages.info(request, _("You have voted."))
chris's avatar
chris committed
248 249 250 251 252 253 254
                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
Christophe Siraut committed
255
                    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') ]
chris's avatar
chris committed
256 257 258 259

            except:
                pass
        else:
260 261 262 263 264
            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."))
chris's avatar
chris committed
265 266 267 268
            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
Christophe Siraut committed
269
                    bulletin = Bulletin.objects.get(poll=poll, voter=voter)
270 271
                    messages.success(request, _('%s has voted and can still modify its vote.') % voter)
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
chris's avatar
chris committed
272 273 274 275 276 277 278
                    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.
                        """
279
                        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') ]
chris's avatar
chris committed
280 281 282

                except:
                    pass
283 284 285
            else:
                if voter:
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
chris's avatar
chris committed
286

287
    form = BulletinForm(instance=poll, initial={'voter': voter})
Christophe Siraut's avatar
Christophe Siraut committed
288 289 290
    return render(request,
                  'meetingpoll/poll_detail.html',
                  {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted})
291

chris's avatar
chris committed
292

293
def exp_csv(request, poll_id):
chris's avatar
chris committed
294 295 296
    import csv

    # Create the HttpResponse object with the appropriate CSV header.
chris's avatar
chris committed
297
    response = HttpResponse(content_type='text/csv')
chris's avatar
chris committed
298 299
    response['Content-Disposition'] = 'attachment; filename=nuages.csv'

Christophe Siraut's avatar
Christophe Siraut committed
300
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
301 302
    choices = Choice.objects.filter(poll=poll)
    bulletins = Bulletin.objects.filter(poll=poll)
chris's avatar
chris committed
303 304 305
    writer = csv.writer(response, quotechar='"', quoting=csv.QUOTE_ALL)
    fr = ["",]
    for c in choices:
Christophe Siraut's avatar
Christophe Siraut committed
306
        fr.append(c)
chris's avatar
chris committed
307 308 309 310 311 312 313
    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
314

Christophe Siraut's avatar
Christophe Siraut committed
315 316 317 318 319 320 321 322 323 324 325 326 327 328
@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})


329 330 331
def clear_cookie(request, poll_id):
    request.session.clear()
    return HttpResponseRedirect(reverse('vote', args=(poll_id,)))