views.py 13.7 KB
Newer Older
1
2
3
4
5
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import get_current_site
from django.core.exceptions import ObjectDoesNotExist
christophe siraut's avatar
christophe siraut committed
6
7
8
from django.core.urlresolvers import reverse
from django.forms.formsets import formset_factory
from django.forms.models import inlineformset_factory, BaseInlineFormSet
9
from django.http import HttpResponse, HttpResponseRedirect
10
from django.shortcuts import  get_object_or_404, render_to_response, render
11
from django.template import RequestContext
12
from django.utils.translation import ugettext_lazy as _
13
from account.forms import UserProfileForm
14
15
16
from account.views import email_notify
from meetingpoll.forms import PollForm, ChoiceForm, VoteForm, BulletinForm
from meetingpoll.models import Poll, Choice, Vote, Bulletin
christophe siraut's avatar
christophe siraut committed
17
18

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

def get_ordereditem_formset(form, formset=BaseInlineFormSet, **kwargs):
    return inlineformset_factory(Poll, Choice, form, formset, **kwargs)

def editchoices(request, poll_id):

Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
44
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
christophe siraut's avatar
christophe siraut committed
45
    language_code = request.LANGUAGE_CODE
46
    if request.user.is_anonymous(): # Anonymous wants to edit his new poll
christophe siraut's avatar
christophe siraut committed
47
48
        key = 'is_' + poll_id + '_author'
        if not request.session.get(key, False):
49
            return HttpResponseRedirect(reverse('home'))
christophe siraut's avatar
christophe siraut committed
50
    else:
51
52
        if request.user != poll.user:
            return HttpResponseRedirect(reverse('home'))
christophe siraut's avatar
christophe siraut committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

    OrderedItemFormset = get_ordereditem_formset(ChoiceForm, extra=0, can_delete=True)

    if request.method == "POST":
        """
        Should we set a maximum of choices here?
        #instances = request.POST.values()
        if len(instances) < 20:
            for selection in instances:
        """
        instances = OrderedItemFormset(request.POST, instance=poll)
        if instances.is_valid():
            for instance in instances.cleaned_data:
                try:
                    this_choice = instance['choice']
                    if not instance.get('DELETE'):
                        try:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
70
                            choice = Choice.objects.get(poll=poll, choice=instance['choice'])
christophe siraut's avatar
christophe siraut committed
71
72
                            choice.details = instance['details']
                            choice.save()
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
73
                        except ObjectDoesNotExist:
christophe siraut's avatar
christophe siraut committed
74
75
                            choice = Choice(poll=poll, choice=instance['choice'], details=instance['details'])
                            choice.save()
76
77
78
79
80
81
                            # If bulletins for this poll existed before edition
                            # add an 'false' vote child to them for newly created choice.
                            # This makes template computation easier
                            for bulletin in Bulletin.objects.filter(poll=poll):
                                nvote = Vote(choice=choice, bulletin=bulletin, voice=False)
                                nvote.save()
christophe siraut's avatar
christophe siraut committed
82
83
                    else:
                        try:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
84
                            choice = Choice.objects.get(poll=poll, choice=this_choice)
christophe siraut's avatar
christophe siraut committed
85
86
87
88
89
90
91
                            """
                            Removing a Choice will remove all childeren Vote objects.
                            When Django deletes an object, it emulates the behavior of
                            the SQL constraint ON DELETE CASCADE -- in other words, any
                            objects which had foreign keys pointing at the object to be
                            deleted will be deleted along with it."""
                            choice.delete()
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
92
                        except :
christophe siraut's avatar
christophe siraut committed
93
94
                            pass
                except:
95
96
                    # probably an empty datefield?
                    pass 
97
            return HttpResponseRedirect(poll.link)
christophe siraut's avatar
christophe siraut committed
98
        else:
99
            #vforms=OrderedItemFormset(request.POST, instance=poll)
100
            messages.error(request, _("There are some errors in the form you posted."))
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
101
            vforms = instances
102

christophe siraut's avatar
christophe siraut committed
103
    else:
104
105
        if Choice.objects.filter(poll=poll_id).count() == 0:
            # Sall we replace next line with something like OrderedItemFormset(extra=2)
106
            OrderedItemFormset = get_ordereditem_formset(ChoiceForm, extra=1, can_delete=True)
107
            vforms = OrderedItemFormset(instance=poll)
108
109
110
        else:
            vforms = OrderedItemFormset(instance=poll)

111
112
113
    return render_to_response('meetingpoll/choice_form.html',
        {'object': poll, 'vforms': vforms, 'language_code': language_code,},
         context_instance=RequestContext(request))
114

christophe siraut's avatar
christophe siraut committed
115

116
117
118
@login_required
def delete(request, poll_id):

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

121
    if poll.user == request.user:
122
123
124
125
126
        poll.delete()

    return HttpResponseRedirect('/')


christophe siraut's avatar
christophe siraut committed
127
128
129
130
131
def make_buletin_form(poll, **kwargs):
    return [ [VoteForm(prefix=choice) ] for choice in Choice.objects.filter(poll=poll.id) ]


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

    if request.method == 'POST':
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
136
        form = BulletinForm(request.POST, initial={'poll': poll.id,})
Christophe Siraut's avatar
Christophe Siraut committed
137
        vforms = [ [VoteForm(request.POST, prefix=choice, instance=choice) ] for choice in Choice.objects.filter(poll=poll.id) ]
christophe siraut's avatar
christophe siraut committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

        if form.is_valid():           
            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')

            if voter != 'your name':
                """
                try:
                    Bulletin.objects.get(poll=poll.id,voter=voter)
                    return render_to_response('sondage/poll_detail.html', {'object': poll, 'form': form, 'vforms':vforms, 'error_message':error_message}, context_instance=RequestContext(request))
                except:
                    pass
                """

Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
156
157
                if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                    bulletin = Bulletin(poll=poll, voter=voter)
christophe siraut's avatar
christophe siraut committed
158
159
                    bulletin.save()
                else:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
160
                    bulletin = Bulletin.objects.get(poll=poll.id, voter=voter)
christophe siraut's avatar
christophe siraut committed
161
162
163
164
165

                for forms in vforms:
                    for vorm in forms:
                        if vorm.is_valid():
                            try:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
166
                                choice = Choice.objects.get(choice=vorm.cleaned_data['choice'], poll=poll)
christophe siraut's avatar
christophe siraut committed
167
                            except:
168
                                return HttpResponse(vorm.cleaned_data['choice'])
christophe siraut's avatar
christophe siraut committed
169

Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
170
171
                            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
172
173
                                if vorm.cleaned_data['voice']:
                                    new.voice = vorm.cleaned_data['voice']
christophe siraut's avatar
christophe siraut committed
174
175
176
177
178
179
180
181
                                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
182
                                    has_voted = True  # Used to show "Forget me"
christophe siraut's avatar
christophe siraut committed
183
                            else:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
184
                                old = Vote.objects.get(choice=choice, bulletin=bulletin)
christophe siraut's avatar
christophe siraut committed
185
186
187
188
189
190
191
192
193
194
195
196
197

                                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()
198
199
                                is_updated = True
                if has_voted:
200
                    messages.success(request, _("Your vote has been counted, thank you."))
201
                if is_updated:
202
                    messages.success(request, _("Your vote has been updated, thank you."))
203
204
205
206
207
208
                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
209
            else:
210
                messages.error(request, _('Did you forget to provide your name?'))
christophe siraut's avatar
christophe siraut committed
211
        else:
212
            messages.error(request, _('Did you forget to provide your name?'))
213
            voter = _('your name')
christophe siraut's avatar
christophe siraut committed
214
215
216
217
218
219
220
221
222

    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
223
            vforms = [ [ VoteForm(initial={'choice': choice,}, prefix=choice) ] for choice in Choice.objects.filter(poll=poll_id) ]
christophe siraut's avatar
christophe siraut committed
224
225
226
227
        if request.user.is_authenticated():
            voter = str(request.user)
            try:
                bulletin = Bulletin.objects.get(poll=poll,voter=voter)
228
                messages.info(request, _("You have voted."))
christophe siraut's avatar
christophe siraut committed
229
230
231
232
233
234
235
                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
236
                    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
237
238
239
240

            except:
                pass
        else:
241
242
243
244
245
            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
246
247
248
249
            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
250
                    bulletin = Bulletin.objects.get(poll=poll, voter=voter)
251
252
                    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
253
254
255
256
257
258
259
                    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.
                        """
260
                        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
261
262
263

                except:
                    pass
264
265
266
            else:
                if voter:
                    messages.info(request, _('Not %s? Click Forget me.') % voter)
christophe siraut's avatar
christophe siraut committed
267

268
269
    form = BulletinForm(instance=poll,initial={'voter': voter})
    #form = BulletinForm(instance=poll)
270
    return render_to_response('meetingpoll/poll_detail.html', {'object': poll, 'form': form, 'vforms':vforms, 'has_voted': has_voted}, context_instance=RequestContext(request))
christophe siraut's avatar
christophe siraut committed
271

chris's avatar
chris committed
272
def exp_csv(request, poll_id):
Christophe Siraut's avatar
Christophe Siraut committed
273
274
275
276
277
278
    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
279
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
chris's avatar
chris committed
280
281
    choices = Choice.objects.filter(poll=poll)
    bulletins = Bulletin.objects.filter(poll=poll)
Christophe Siraut's avatar
Christophe Siraut committed
282
283
284
    writer = csv.writer(response, quotechar='"', quoting=csv.QUOTE_ALL)
    fr = ["",]
    for c in choices:
Christophe Siraut's avatar
Cleanup    
Christophe Siraut committed
285
        fr.append(c)
Christophe Siraut's avatar
Christophe Siraut committed
286
287
288
289
290
291
292
    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