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