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 django.views.generic.create_update import update_object
14
from account.forms import UserProfileForm
15 16 17
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
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
        if request.user.is_anonymous():
            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 44 45 46 47 48 49 50 51 52 53

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

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

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

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

121 122 123
    return render_to_response('meetingpoll/choice_form.html',
        {'object': poll, 'vforms': vforms, '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
    has_voted, is_updated = False, False
christophe siraut's avatar
christophe siraut committed
144 145

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

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

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

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

                                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()
208 209 210 211 212
                                is_updated = True
                if has_voted:
                    messages.info(request, _("Your vote has been counted, thank you."))
                if is_updated:
                    messages.info(request, _("Your vote has been updated, thank you."))
213 214 215 216 217 218
                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
                messages.error(request, _('Did you forget to provide your name?'))
christophe siraut's avatar
christophe siraut committed
221
        else:
222
            messages.error(request, _('Did you forget to provide your name?'))
223
            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
                messages.info(request, _("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
            messages.info(request, _("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
                    messages.info(request, _('%s has voted') % voter)
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
    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
276

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