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.contrib.sites.models import get_current_site
13
from django.conf import settings
14 15 16 17
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
18 19

def new(request):
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
20
    if request.method == 'POST':
21
        form = PollForm(request.POST)
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
22
        if form.is_valid():
23 24 25 26 27 28 29
            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
30
    else:
31 32 33 34 35
        form = PollForm()
    return render_to_response(
        'meetingpoll/poll_form.html',
        {'form': form},
        context_instance=RequestContext(request))
christophe siraut's avatar
christophe siraut committed
36 37 38 39 40 41 42 43 44 45 46

@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)

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

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

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

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

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

christophe siraut's avatar
christophe siraut committed
126

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

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

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

    return HttpResponseRedirect('/')


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

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

        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
169 170
                if not Bulletin.objects.filter(poll=poll.id, voter=voter):
                    bulletin = Bulletin(poll=poll, voter=voter)
christophe siraut's avatar
christophe siraut committed
171 172
                    bulletin.save()
                else:
Christophe Siraut's avatar
Cleanup  
Christophe Siraut committed
173
                    bulletin = Bulletin.objects.get(poll=poll.id, voter=voter)
christophe siraut's avatar
christophe siraut committed
174 175 176 177 178

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

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

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

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

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

                except:
                    pass

274 275
    form = BulletinForm(instance=poll,initial={'voter': voter})
    #form = BulletinForm(instance=poll)
276
    return render_to_response('meetingpoll/poll_detail.html', {'object': poll, 'form': form, 'vforms':vforms, 'error_message':error_message, 'has_voted': has_voted}, 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