views.py 13.7 KB
Newer Older
christophe siraut's avatar
christophe siraut committed
1
from django.http import HttpResponse, HttpResponseRedirect
2
from django.core.urlresolvers import reverse
christophe siraut's avatar
christophe siraut committed
3 4 5 6 7
from django.shortcuts import  get_object_or_404, render_to_response
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.forms.formsets import formset_factory
from django.forms.models import inlineformset_factory, BaseInlineFormSet
8
from django.core.exceptions import ObjectDoesNotExist
christophe siraut's avatar
christophe siraut committed
9 10
from django.views.generic.create_update import update_object
from django.contrib.auth.decorators import login_required
11
from django.utils.translation import ugettext_lazy as _
12
from django.conf import settings
13 14 15 16
from meetingpoll.models import Poll, Choice, Vote, Bulletin
from meetingpoll.forms import PollForm, ChoiceForm, VoteForm, BulletinForm
from account.views import email_notify
from account.forms import UserProfileForm
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 31 32 33 34
        form = PollForm()
    return render_to_response(
        'meetingpoll/poll_form.html',
        {'form': form},
        context_instance=RequestContext(request))
christophe siraut's avatar
christophe siraut committed
35 36 37 38 39 40 41 42 43 44 45

@login_required
def secure_update_object(*args, **kwargs):
    """
    Souldn't we provide a better object to the generic view: object_id=poll
    and then simple the template
    # joe = str(request.user)
    # if Poll.objects.get(id=object_id, author=joe):
    """
    return update_object(*args, **kwargs)

46 47 48
def translation(request, lang_id):
    request.session['django_language'] = lang_id
    return HttpResponseRedirect('/nuages')
christophe siraut's avatar
christophe siraut committed
49 50 51 52 53 54

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
55
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
christophe siraut's avatar
christophe siraut committed
56
    language_code = request.LANGUAGE_CODE
57
    error_message = ''
58
    if request.user.is_anonymous(): # Anonymous wants to edit his new poll
christophe siraut's avatar
christophe siraut committed
59 60
        key = 'is_' + poll_id + '_author'
        if not request.session.get(key, False):
61
            return HttpResponseRedirect(reverse('home'))
christophe siraut's avatar
christophe siraut committed
62
    else:
63 64
        if request.user != poll.user:
            return HttpResponseRedirect(reverse('home'))
christophe siraut's avatar
christophe siraut committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

    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
82
                            choice = Choice.objects.get(poll=poll, choice=instance['choice'])
christophe siraut's avatar
christophe siraut committed
83 84
                            choice.details = instance['details']
                            choice.save()
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
85
                        except ObjectDoesNotExist:
christophe siraut's avatar
christophe siraut committed
86 87
                            choice = Choice(poll=poll, choice=instance['choice'], details=instance['details'])
                            choice.save()
88 89 90 91 92 93
                            # 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
94 95
                    else:
                        try:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
96
                            choice = Choice.objects.get(poll=poll, choice=this_choice)
christophe siraut's avatar
christophe siraut committed
97 98 99 100 101 102 103
                            """
                            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
104
                        except :
christophe siraut's avatar
christophe siraut committed
105 106
                            pass
                except:
107 108
                    # probably an empty datefield?
                    pass 
109
            return HttpResponseRedirect(poll.link)
christophe siraut's avatar
christophe siraut committed
110
        else:
111
            #vforms=OrderedItemFormset(request.POST, instance=poll)
112
            error_message = _("There are some errors in the form you posted.")
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
113
            vforms = instances
114

christophe siraut's avatar
christophe siraut committed
115
    else:
116 117
        if Choice.objects.filter(poll=poll_id).count() == 0:
            # Sall we replace next line with something like OrderedItemFormset(extra=2)
118
            OrderedItemFormset = get_ordereditem_formset(ChoiceForm, extra=1, can_delete=True)
119
            vforms = OrderedItemFormset(instance=poll)
120 121 122
        else:
            vforms = OrderedItemFormset(instance=poll)

123
    return render_to_response('meetingpoll/choice_form.html', {'object': poll, 'vforms': vforms, 'error_message' : error_message, 'language_code': language_code,}, context_instance=RequestContext(request))
124

christophe siraut's avatar
christophe siraut committed
125

126 127 128
@login_required
def delete(request, poll_id):

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

131
    if poll.user == request.user:
132 133 134 135 136
        poll.delete()

    return HttpResponseRedirect('/')


christophe siraut's avatar
christophe siraut committed
137 138 139 140 141
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
142
    poll = get_object_or_404(Poll.objects.all(), id=poll_id)
143
    error_message = None
144
    has_voted = False
christophe siraut's avatar
christophe siraut committed
145 146

    if request.method == 'POST':
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
147
        form = BulletinForm(request.POST, initial={'poll': poll.id,})
Christophe Siraut's avatar
Christophe Siraut committed
148
        vforms = [ [VoteForm(request.POST, prefix=choice, instance=choice) ] for choice in Choice.objects.filter(poll=poll.id) ]
christophe siraut's avatar
christophe siraut committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167

        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)
                    error_message = 'A user with the same name has already voted.'
                    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
168 169
                if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                    bulletin = Bulletin(poll=poll, voter=voter)
christophe siraut's avatar
christophe siraut committed
170 171
                    bulletin.save()
                else:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
172
                    bulletin = Bulletin.objects.get(poll=poll.id, voter=voter)
christophe siraut's avatar
christophe siraut committed
173 174 175 176 177

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

Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
182 183
                            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
184 185
                                if vorm.cleaned_data['voice']:
                                    new.voice = vorm.cleaned_data['voice']
christophe siraut's avatar
christophe siraut committed
186 187 188 189 190 191 192 193 194
                                new.save()
                                if new.voice:
                                    choice.votecount += 1
                                    choice.save()
                                error_message = "Your vote has been counted, thank you."
                                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
195
                                    has_voted = True  # Used to show "Forget me"
christophe siraut's avatar
christophe siraut committed
196
                            else:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
197
                                old = Vote.objects.get(choice=choice, bulletin=bulletin)
christophe siraut's avatar
christophe siraut committed
198 199 200 201 202 203 204 205 206 207 208 209 210

                                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()
211 212 213 214 215 216 217
                                error_message = _("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
218
            else:
219
                error_message = _('Did you forget to provide your name?')
christophe siraut's avatar
christophe siraut committed
220 221
        else:
            #error_message = form.errors
222 223
            error_message = _('Did you forget to provide your name?')
            voter = _('your name')
christophe siraut's avatar
christophe siraut committed
224 225 226 227 228 229 230 231 232

    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
233
            vforms = [ [ VoteForm(initial={'choice': choice,}, prefix=choice) ] for choice in Choice.objects.filter(poll=poll_id) ]
christophe siraut's avatar
christophe siraut committed
234 235 236 237
        if request.user.is_authenticated():
            voter = str(request.user)
            try:
                bulletin = Bulletin.objects.get(poll=poll,voter=voter)
238
                error_message = " You have voted."
christophe siraut's avatar
christophe siraut committed
239 240 241 242 243 244 245
                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
246
                    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
247 248 249 250

            except:
                pass
        else:
251
            voter = ''
252
            error_message = _("Login let you modify your vote anytime.")
christophe siraut's avatar
christophe siraut committed
253 254
            key = 'has_voted-' + poll.id
            if request.session.get(key, False):
255
                has_voted = True  # Used to show "Forget me"
christophe siraut's avatar
christophe siraut committed
256 257 258
                voter = request.session.get('name')
                #error_message = 'Modify your vote? (clear cookie if you are not ' + voter + ')'
                try:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
259
                    bulletin = Bulletin.objects.get(poll=poll, voter=voter)
260
                    error_message = voter + ' has voted'
christophe siraut's avatar
christophe siraut committed
261 262 263 264 265 266 267
                    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.
                        """
268
                        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
269 270 271 272

                except:
                    pass

273 274
    form = BulletinForm(instance=poll,initial={'voter': voter})
    #form = BulletinForm(instance=poll)
275
    current_site = settings.SITE + poll.id
276
    return render_to_response('meetingpoll/poll_detail.html', {'object': poll, 'form': form, 'vforms':vforms, 'error_message':error_message, 'has_voted': has_voted, 'current_site': current_site}, context_instance=RequestContext(request))
christophe siraut's avatar
christophe siraut committed
277

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