views.py 14.2 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
7
from django.shortcuts import get_object_or_404, render, HttpResponseRedirect, HttpResponse
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
        formset = choiceFormset(request.POST, instance=poll)
        if formset.is_valid():
            formset.save()
            if not '_addanother' in request.POST:
69 70 71 72 73 74 75 76 77 78 79 80

                voter = get_voter_name(request)
                if not voter:
                    voter = 'Anonymous'
                if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                    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()
                    poll.save()
81 82 83 84
                    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
85

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

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

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

christophe siraut's avatar
christophe siraut committed
103

104 105 106
@login_required
def delete(request, poll_id):

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

109
    if poll.user == request.user:
110 111 112 113 114
        poll.delete()

    return HttpResponseRedirect('/')


christophe siraut's avatar
christophe siraut committed
115
def make_buletin_form(poll, **kwargs):
116
    return [[VoteForm(prefix=choice)] for choice in Choice.objects.filter(poll=poll.id)]
christophe siraut's avatar
christophe siraut committed
117 118


119 120 121 122 123 124 125 126 127
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')

christophe siraut's avatar
christophe siraut committed
128
def vote(request, poll_id):
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
129
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
130
    has_voted, is_updated = False, False
christophe siraut's avatar
christophe siraut committed
131 132

    if request.method == 'POST':
133

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

138
        if form.is_valid():
139 140

            if request.POST.get('trap', False):
141 142
                return render(
                    request,
143
                    'meetingpoll/poll_detail.html',
144 145 146 147
                    {'object': poll,
                     'form': form,
                     'vforms': vforms,
                     'has_voted': has_voted})
148

149
            voter = get_voter_name(request, form)
christophe siraut's avatar
christophe siraut committed
150

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
            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})

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
            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:
                            return render(request, vorm.cleaned_data['choice'])

                        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:
Christophe Siraut's avatar
Christophe Siraut committed
212
                                if vorm.cleaned_data['voice']:
christophe siraut's avatar
christophe siraut committed
213 214
                                    choice.votecount += 1
                                    choice.save()
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

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

            if has_voted:
                messages.success(request, _("Your vote has been counted, thank you."))
            if is_updated:
                messages.success(request, _("Your vote has been updated, thank you."))
            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
232
        else:
233
            messages.error(request, _('Did you forget to provide your name?'))
234
            voter = _('your name')
christophe siraut's avatar
christophe siraut committed
235 236 237 238 239 240 241 242 243

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

            except:
                pass
        else:
262 263 264 265 266
            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
267 268 269 270
            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
271
                    bulletin = Bulletin.objects.get(poll=poll, voter=voter)
272 273
                    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
274 275 276 277 278 279 280
                    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.
                        """
281
                        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
282 283 284

                except:
                    pass
285 286 287
            else:
                if voter:
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
christophe siraut's avatar
christophe siraut committed
288

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

christophe siraut's avatar
christophe siraut committed
294

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

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


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