views.py 13.8 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
        if request.user.is_anonymous():
32
            request.session.clear()
33
            messages.warning(request, _('You are not logged so you will not be able to modify your poll after creation or recieve notifications.'))
34 35 36 37 38
        form = PollForm()
    return render_to_response(
        'meetingpoll/poll_form.html',
        {'form': form},
        context_instance=RequestContext(request))
christophe siraut's avatar
christophe siraut committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

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

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

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

122 123 124
    return render_to_response('meetingpoll/choice_form.html',
        {'object': poll, 'vforms': vforms, '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
    has_voted, is_updated = False, 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

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

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

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

                                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()
209 210 211 212 213
                                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."))
214 215 216 217 218 219
                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
220
            else:
221
                messages.error(request, _('Did you forget to provide your name?'))
christophe siraut's avatar
christophe siraut committed
222
        else:
223
            messages.error(request, _('Did you forget to provide your name?'))
224
            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
                messages.info(request, _("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
            messages.info(request, _("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
                    messages.info(request, _('%s has voted') % voter)
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, '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