source: asadb/forms/views.py @ 5e018d9

space-accessstablestage
Last change on this file since 5e018d9 was 5e018d9, checked in by Alex Dehnert <adehnert@…>, 13 years ago

Fix spelling of midway permission

  • Property mode set to 100644
File size: 24.3 KB
RevLine 
[26826c9]1import collections
2import csv
3import datetime
4import StringIO
[90afb00]5
[afc5348]6from django.conf import settings
[0b72bfd]7from django.contrib.auth.decorators import user_passes_test, login_required, permission_required
[bda4d86]8from django.core.exceptions import PermissionDenied
[ea42397]9from django.views.generic import list_detail, ListView, DetailView
[aba463b]10from django.shortcuts import render_to_response, get_object_or_404
[90afb00]11from django.template import RequestContext
[f921734]12from django.template import Context, Template
13from django.template.loader import get_template
[0b72bfd]14from django.http import Http404, HttpResponseRedirect, HttpResponse
[90afb00]15from django.core.urlresolvers import reverse
[d199ba4]16from django.core.mail import EmailMessage, mail_admins
[d848b98]17from django.forms import FileField
[90afb00]18from django.forms import Form
19from django.forms import ModelForm
[b1a8ea7]20from django.forms import ModelChoiceField, ModelMultipleChoiceField
[3496370]21from django.forms import ValidationError
[4260e2c]22from django.db import connection
[ea42397]23from django.db.models import Q, Count
[aba463b]24
[f610262]25import django_filters
26
[26826c9]27import forms.models
28import groups.models
29import groups.views
30import util.emails
[aba463b]31
[90afb00]32#################
33# GENERIC VIEWS #
34#################
35
36class SelectGroupForm(Form):
37    group = ModelChoiceField(queryset=groups.models.Group.objects.all())
[2f7114b]38    def __init__(self, *args, **kwargs):
39        queryset = None
40        if 'queryset' in kwargs:
41            queryset = kwargs['queryset']
42            del kwargs['queryset']
[f921734]43        super(SelectGroupForm, self).__init__(*args, **kwargs)
44        if queryset is not None:
45            self.fields["group"].queryset = queryset
[90afb00]46
[bda4d86]47def select_group(request, url_name_after, url_args=[], pagename='homepage', queryset=None, title="", msg=""):
[90afb00]48    if request.method == 'POST': # If the form has been submitted...
[f921734]49        # A form bound to the POST data
50        form = SelectGroupForm(request.POST, queryset=queryset, )
[90afb00]51        if form.is_valid(): # All validation rules pass
52            group = form.cleaned_data['group'].id
[bda4d86]53            return HttpResponseRedirect(reverse(url_name_after, args=url_args+[group],)) # Redirect after POST
[90afb00]54    else:
[f921734]55        form = SelectGroupForm(queryset=queryset, ) # An unbound form
[90afb00]56
[bda4d86]57    if not title: title = "Select group"
[90afb00]58    context = {
59        'form':form,
[bda4d86]60        'title':title,
61        'msg':msg,
[0b488d4]62        'pagename':pagename,
[90afb00]63    }
64    return render_to_response('forms/select.html', context, context_instance=RequestContext(request), )
65
66#############################
67# FIRST-YEAR SUMMER MAILING #
68#############################
69
[00e16ed]70@login_required
[97399af]71def fysm_by_years(request, year, category, ):
[aba463b]72    if year is None: year = datetime.date.today().year
73    queryset = forms.models.FYSM.objects.filter(year=year).order_by('group__name')
[dafa3c8]74    category_obj = None
[a10dd4b]75    category_name = 'main'
[dafa3c8]76    if category != None:
[c27da9e]77        category_obj = get_object_or_404(forms.models.FYSMCategory, slug=category)
[a10dd4b]78        category_name = category_obj.name
[c27da9e]79        queryset = queryset.filter(categories=category_obj)
[a10dd4b]80    forms.models.FYSMView.record_metric(request=request, fysm=None, year=year, page=category_name, )
[c27da9e]81    categories = forms.models.FYSMCategory.objects.all()
[aba463b]82    return list_detail.object_list(
83        request,
84        queryset=queryset,
[90afb00]85        template_name="fysm/fysm_listing.html",
[aba463b]86        template_object_name="fysm",
87        extra_context={
88            "year": year,
89            "pagename": "fysm",
[dafa3c8]90            "category": category_obj,
[189506e]91            "categories": categories,
[aba463b]92        }
93    )
[90afb00]94
[00e16ed]95@login_required
[aaa8e04]96def fysm_view(request, year, submission, ):
[ae881e5]97    submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,)
98    all = forms.models.FYSM.objects.only("id", "display_name", )
99    try:
100        prev = all.filter(display_name__lt=submit_obj.display_name).order_by("-display_name")[0]
101    except IndexError:
102        prev = None
103    try:
104        next = all.filter(display_name__gt=submit_obj.display_name).order_by("display_name")[0]
105    except IndexError:
106        next = None
[a10dd4b]107    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page="detail", )
[aaa8e04]108    return list_detail.object_detail(
109        request,
110        forms.models.FYSM.objects,
111        object_id=submission,
112        template_name="fysm/fysm_detail.html",
113        template_object_name="fysm",
114        extra_context={
115            "year": year,
116            "pagename": "fysm",
[ae881e5]117            "prev": prev,
118            "next": next,
[aaa8e04]119        },
120    )
121
[f462be6]122def fysm_link(request, year, link_type, submission, ):
123    submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,)
124    if submit_obj.year != int(year):
125        raise Http404("Year mismatch: fysm.year='%s', request's year='%s'" % (submit_obj.year, year, ))
126    if link_type == 'join':
127        url = submit_obj.join_url
128    elif link_type == 'website':
129        url = submit_obj.website
130    else:
131        raise Http404("Unknown link type")
[a10dd4b]132    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page=link_type, )
[f462be6]133    return HttpResponseRedirect(url)
134
[f921734]135def select_group_fysm(request, ):
[2c0eaa1]136    qobj = Q(activity_category__isnull = True) | ~(Q(activity_category__name='Dorm') | Q(activity_category__name='FSILG'))
[d3167b9]137    queryset = groups.models.Group.active_groups.filter(qobj)
[f921734]138    return select_group(
139        request,
140        url_name_after='fysm-manage',
141        pagename='fysm',
142        queryset=queryset,
143    )
144
[90afb00]145class FYSMRequestForm(ModelForm):
146    class Meta:
147        model = forms.models.FYSM
148        fields = (
149            'display_name',
150            'website',
151            'join_url',
152            'contact_email',
153            'description',
154            'logo',
[3400018]155            'slide',
[57f8ffa]156            'tags',
[c27da9e]157            'categories',
[90afb00]158        )
159
[3496370]160    def clean_display_name(self, ):
161        name = self.cleaned_data['display_name']
162        if ',' in name:
163            raise ValidationError("""In general, commas in a display name are a mistake and will look bad (group names like "Punctuation Society, MIT" should probably be "Punctuation Society"). If you do want a comma, contact asa-fysm@mit.edu and we'll put it in for you.""")
164        return name
165
[cbdbd1f]166    def clean_description(self, ):
167        description = self.cleaned_data['description']
168        length = len(description)
169        if length > 400:
170            raise ValidationError("Descriptions are capped at 400 characters, and this one is %d characters." % (length, ))
171        return description
172
[00e16ed]173@login_required
[90afb00]174def fysm_manage(request, group, ):
175    year = datetime.date.today().year
176    group_obj = get_object_or_404(groups.models.Group, pk=group)
177
178    initial = {}
179    try:
180        fysm_obj = forms.models.FYSM.objects.get(group=group_obj, year=year, )
181    except forms.models.FYSM.DoesNotExist:
182        fysm_obj = forms.models.FYSM()
183        fysm_obj.group = group_obj
184        fysm_obj.year = year
185        initial['display_name'] = group_obj.name
186        initial['year'] = year
187        initial['website'] = group_obj.website_url
188        initial['join_url'] = group_obj.website_url
189        initial['contact_email'] = group_obj.officer_email
190
191    if request.method == 'POST': # If the form has been submitted...
192        form = FYSMRequestForm(request.POST, request.FILES, instance=fysm_obj, ) # A form bound to the POST data
193
194        if form.is_valid(): # All validation rules pass
195            request_obj = form.save()
196
[1f4ee0b]197            view_uri = request.build_absolute_uri(reverse('fysm-view', args=[year, request_obj.pk, ]))
[adfe18c]198
[90afb00]199            # Send email
[cd98e17]200            email = util.emails.email_from_template(
201                tmpl='fysm/update_email.txt',
202                context = Context({
203                    'group': group_obj,
204                    'fysm': fysm_obj,
205                    'view_uri': view_uri,
206                    'submitter': request.user,
207                    'request': request,
208                    'sender': "ASA FYSM team",
209                }),
[d199ba4]210                subject='FYSM entry for "%s" updated by "%s"' % (
[90afb00]211                    group_obj.name,
212                    request.user,
213                ),
[c49fbe2]214                to=[group_obj.officer_email, request.user.email, ],
[cd98e17]215                from_email='asa-fysm@mit.edu',
[90afb00]216            )
[cd98e17]217            email.bcc = ['asa-fysm-submissions@mit.edu']
[d199ba4]218            email.send()
[90afb00]219            return HttpResponseRedirect(reverse('fysm-thanks', args=[fysm_obj.pk],)) # Redirect after POST
220
221    else:
222        form = FYSMRequestForm(instance=fysm_obj, initial=initial, ) # An unbound form
223
224    context = {
225        'group':group_obj,
226        'fysm':fysm_obj,
227        'form':form,
[07caee0]228        'categories':forms.models.FYSMCategory.objects.all(),
[90afb00]229        'pagename':'fysm',
230    }
231    return render_to_response('fysm/submit.html', context, context_instance=RequestContext(request), )
232
233
234def fysm_thanks(request, fysm, ):
235    year = datetime.date.today().year
236    fysm_obj = get_object_or_404(forms.models.FYSM, pk=fysm)
237
238    context = {
239        'group':fysm_obj.group,
240        'fysm':fysm_obj,
241        'pagename':'fysm',
242    }
243    return render_to_response('fysm/thanks.html', context, context_instance=RequestContext(request), )
[5b834ab]244
245#####################
246# Membership update #
247#####################
248
[055a7e9]249membership_update_qs = groups.models.Group.objects.filter(group_status__slug__in=['active', 'suspended', ])
250
[bda4d86]251@login_required
252def group_membership_update_select_group(request, ):
253    cycle = forms.models.GroupConfirmationCycle.latest()
254
255    users_groups = groups.models.Group.involved_groups(request.user.username)
256    qs = membership_update_qs.filter(pk__in=users_groups)
[b1a8ea7]257
[bda4d86]258    return select_group(request=request,
259        url_name_after='membership-update-group',
260        url_args=[cycle.slug],
261        pagename='groups',
262        queryset=qs,
263        title="Submit membership update for...",
264        msg="The list below contains only groups that list you as being involved. You must be an administrator of a group to submit an update.",
265    )
266
267class Form_GroupMembershipUpdate(ModelForm):
[5b834ab]268    def __init__(self, *args, **kwargs):
269        super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs)
270        self.fields['no_hazing'].required = True
271
272    class Meta:
273        model = forms.models.GroupMembershipUpdate
274        fields = [
275            'updater_title',
276            'group_email',
277            'officer_email',
[185fde1]278            'email_preface',
[5b834ab]279            'no_hazing',
[185fde1]280            'no_discrimination',
[5b834ab]281            'membership_definition',
282            'num_undergrads',
283            'num_grads',
[ceaf3bd]284            'num_alum',
285            'num_other_affiliate',
[5b834ab]286            'num_other',
287            'membership_list',
288        ]
289
290@login_required
[bda4d86]291def group_membership_update(request, cycle_slug, pk, ):
292    cycle = get_object_or_404(forms.models.GroupConfirmationCycle, slug=cycle_slug)
293    group_obj = get_object_or_404(groups.models.Group, pk=pk)
294    if not request.user.has_perm('groups.admin_group', group_obj):
295        raise PermissionDenied
296
297    try:
298        update_obj = forms.models.GroupMembershipUpdate.objects.get(group=group_obj, cycle=cycle, )
299    except forms.models.GroupMembershipUpdate.DoesNotExist:
300        update_obj = None
[5b834ab]301
[1f4ee0b]302    confirm_uri = request.build_absolute_uri(reverse('membership-confirm'))
[6e247d3]303    submitted_uri = request.build_absolute_uri(reverse('membership-submitted'))
[5b834ab]304
[bda4d86]305    if request.method == 'POST':
[5b834ab]306        form = Form_GroupMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data
307
308        if form.is_valid(): # All validation rules pass
[bda4d86]309            # Update the updater info
310            form.instance.group = group_obj
311            form.instance.cycle = cycle
312            form.instance.update_time  = datetime.datetime.now()
313            form.instance.updater_name = request.user.username
[5b834ab]314            request_obj = form.save()
315
316            # Send email
317            tmpl = get_template('membership/anti-hazing.txt')
318            ctx = Context({
319                'update': request_obj,
320                'group': group_obj,
321                'submitter': request.user,
322            })
323            body = tmpl.render(ctx)
324            email = EmailMessage(
[185fde1]325                subject='Anti-Hazing and Non-Discrimination Acknowledgement for %s' % (
[5b834ab]326                    group_obj.name,
327                ),
328                body=body,
329                from_email=request.user.email,
330                to=[request_obj.group_email, ],
331                cc=[request_obj.officer_email, ],
[5c68184]332                bcc=['asa-db-outgoing@mit.edu', ],
[5b834ab]333            )
334            email.send()
335
336            # Send email
337            tmpl = get_template('membership/submit-confirm-email.txt')
338            ctx = Context({
339                'update': request_obj,
340                'group': group_obj,
341                'submitter': request.user,
342                'confirm_uri': confirm_uri,
[6e247d3]343                'submitted_uri': submitted_uri,
[5b834ab]344            })
345            body = tmpl.render(ctx)
346            email = EmailMessage(
347                subject='ASA Membership Information for %s' % (
348                    group_obj.name,
349                ),
350                body=body,
351                from_email=request.user.email,
352                to=[request_obj.officer_email, ],
[5c68184]353                bcc=['asa-db-outgoing@mit.edu', ],
[5b834ab]354            )
355            email.send()
356
357            return HttpResponseRedirect(reverse('membership-thanks', )) # Redirect after POST
358
359    else:
[bda4d86]360        form = Form_GroupMembershipUpdate(instance=update_obj)
[5b834ab]361
362    context = {
363        'form':form,
[bda4d86]364        'group':group_obj,
[c7b6a3a]365        'cycle':cycle,
[5b834ab]366        'confirm_uri': confirm_uri,
367        'pagename':'groups',
368    }
369    return render_to_response('membership/update.html', context, context_instance=RequestContext(request), )
370
371class Form_PersonMembershipUpdate(ModelForm):
[055a7e9]372    groups = ModelMultipleChoiceField(queryset=membership_update_qs)
[5b834ab]373    class Meta:
374        model = forms.models.PersonMembershipUpdate
375        fields = [
376            'groups',
377        ]
378
379@login_required
380def person_membership_update(request, ):
381    initial = {
382    }
[c297267]383    cycle = forms.models.GroupConfirmationCycle.latest()
[ecb0997]384
385    # Initialize/find the PersonMembershipUpdate for this user
[c297267]386    try:
387        update_obj = forms.models.PersonMembershipUpdate.objects.get(
388            username=request.user.username,
389            deleted__isnull=True,
390            cycle=cycle,
391        )
392        selected_groups = update_obj.groups.all()
393    except forms.models.PersonMembershipUpdate.DoesNotExist:
394        update_obj = forms.models.PersonMembershipUpdate()
395        update_obj.update_time  = datetime.datetime.now()
396        update_obj.username = request.user.username
397        update_obj.cycle = cycle
398        selected_groups = []
399
[21c6ad4]400    # Determine whether the submitter is a student or not
[c297267]401    accounts = groups.models.AthenaMoiraAccount
402    try:
403        person = accounts.active_accounts.get(username=request.user.username)
404        if person.is_student():
405            update_obj.valid = forms.models.VALID_AUTOVALIDATED
406        else:
407            update_obj.valid = forms.models.VALID_AUTOREJECTED
408    except accounts.DoesNotExist:
409        pass
410        update_obj.valid = forms.models.VALID_AUTOREJECTED
411
[8dfd3db]412    update_obj.save()
413
[21c6ad4]414    # Find groups that list a role for the user
415    office_holders = groups.models.OfficeHolder.current_holders.filter(person=request.user.username)
416    role_groups = {}
417    for office_holder in office_holders:
418        if office_holder.group.pk not in role_groups:
419            role_groups[office_holder.group.pk] = (office_holder.group, set())
420        role_groups[office_holder.group.pk][1].add(office_holder.role.display_name)
421
422    # Find groups the user searched for
[055a7e9]423    filterset = groups.views.GroupFilter(request.GET, membership_update_qs)
[56e8cb8]424    filtered_groups = filterset.qs.all()
425    show_filtered_groups = ('search' in request.GET)
426
[c297267]427    message = ""
[56e8cb8]428    message_type = "info"
429
[11941e1]430    if update_obj.valid <= forms.models.VALID_UNSET:
431        message = "You are not listed as a student. While you're welcome to confirm your membership in groups anyway, you will not count towards the five student member requirement. If you are a student, please contact asa-exec so that we can correct our records."
432        message_type = "warn"
433
[ecb0997]434    # Handle the single group add/remove forms
435    # * removing previously confirmed groups
436    # * add/remove groups that list the user in a role
437    # * add/remove groups the user searched for
[56e8cb8]438    if request.method == 'POST' and 'add-remove' in request.POST:
439        group = groups.models.Group.objects.get(id=request.POST['group'])
440        if request.POST['action'] == 'remove':
441            if group in update_obj.groups.all():
442                update_obj.groups.remove(group)
[a50f67b]443                message = "You have successfully unconfirmed membership in %s." % (group, )
[56e8cb8]444            else:
[a50f67b]445                message = "Removal failed because you had not confirmed membership in %s." % (group, )
[56e8cb8]446                message_type = "warn"
447        elif request.POST['action'] == 'add':
448            if group in update_obj.groups.all():
[a50f67b]449                message = "Membership in %s already confirmed." % (group, )
[56e8cb8]450                message_type = "warn"
451            else:
452                update_obj.groups.add(group)
[a50f67b]453                message = "You have successfully confirmed membership in %s." % (group, )
[56e8cb8]454        else:
455            message = "Uh, somehow you tried to do something besides adding and removing..."
456            message_type = "alert"
457
[ecb0997]458    # Handle the big list of groups
459    if request.method == 'POST' and 'list' in request.POST:
460        form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj)
461        if form.is_valid():
[5b834ab]462            request_obj = form.save()
[c297267]463            message = "Update saved"
[5b834ab]464    else:
[ecb0997]465        form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, )
[4d79976]466    form.fields['groups'].widget.attrs['size'] = 20
[5b834ab]467
[ecb0997]468    # Render the page
[5b834ab]469    context = {
[21c6ad4]470        'role_groups':role_groups,
[5b834ab]471        'form':form,
[56e8cb8]472        'filter':filterset,
473        'show_filtered_groups':show_filtered_groups,
474        'filtered_groups':filtered_groups,
475        'member_groups':selected_groups,
[c297267]476        'message': message,
[56e8cb8]477        'message_type': message_type,
[5b834ab]478        'pagename':'groups',
479    }
480    return render_to_response('membership/confirm.html', context, context_instance=RequestContext(request), )
[ea42397]481
482
483class View_GroupMembershipList(ListView):
484    context_object_name = "group_list"
485    template_name = "membership/submitted.html"
486
487    def get_queryset(self):
[bda4d86]488        cycle = forms.models.GroupConfirmationCycle.latest()
[ea42397]489        group_updates = forms.models.GroupMembershipUpdate.objects.all()
[4260e2c]490        group_updates = group_updates.filter(
[bda4d86]491            cycle=cycle,
492            group__personmembershipupdate__cycle=cycle,
[4260e2c]493            group__personmembershipupdate__deleted__isnull=True,
494            group__personmembershipupdate__valid__gt=0,
495        )
496        group_updates = group_updates.annotate(num_confirms=Count('group__personmembershipupdate'))
497        #print len(list(group_updates))
498        #for query in connection.queries: print query
[ea42397]499        return group_updates
500
[0b72bfd]501
502@permission_required('groups.view_group_private_info')
503def group_confirmation_issues(request, ):
[d6f8984]504    account_numbers = ("accounts" in request.GET) and request.GET['accounts'] == "1"
505
[0b72bfd]506    active_groups = groups.models.Group.active_groups
507    group_updates = forms.models.GroupMembershipUpdate.objects.all()
508    people_confirmations = forms.models.PersonMembershipUpdate.objects.filter(
509        deleted__isnull=True,
510        valid__gt=0,
511    )
512
513    buf = StringIO.StringIO()
514    output = csv.writer(buf)
[d6f8984]515    fields = ['group_id', 'group_name', 'issue', 'num_confirm', 'officer_email', ]
516    if account_numbers: fields.append("main_account")
517    output.writerow(fields)
[0b72bfd]518
519    q_present = Q(id__in=group_updates.values('group'))
520    missing_groups = active_groups.filter(~q_present)
521    #print len(list(group_updates))
522    for group in missing_groups:
523        num_confirms = len(people_confirmations.filter(groups=group))
[d6f8984]524        fields = [
[0b72bfd]525            group.id,
526            group.name,
527            'unsubmitted',
528            num_confirms,
529            group.officer_email,
[d6f8984]530        ]
531        if account_numbers: fields.append(group.main_account_id)
532        output.writerow(fields)
[0b72bfd]533
534    for group_update in group_updates:
535        group = group_update.group
536        num_confirms = len(people_confirmations.filter(groups=group))
[de025c2]537        problems = []
538
[0b72bfd]539        if num_confirms < 5:
[de025c2]540            problems.append("confirmations")
541
542        num_students = group_update.num_undergrads + group_update.num_grads
543        num_other = group_update.num_alum + group_update.num_other_affiliate + group_update.num_other
544        if num_students < num_other:
545            problems.append("50%")
546
547        for problem in problems:
[d6f8984]548            fields = [
[0b72bfd]549                group.id,
550                group.name,
[de025c2]551                problem,
[0b72bfd]552                num_confirms,
553                group.officer_email,
[d6f8984]554            ]
555            if account_numbers: fields.append(group.main_account_id)
556            output.writerow(fields)
[0b72bfd]557
558
[360b3d4]559    return HttpResponse(buf.getvalue(), mimetype='text/csv', )
[d848b98]560
561
562
563##########
564# Midway #
565##########
566
[1cfab5a]567def midway_map_latest(request, ):
568    midways = forms.models.Midway.objects.order_by('-date')[:1]
569    if len(midways) == 0:
570        raise Http404("No midways found.")
571    else:
572        url = reverse('midway-map', args=(midways[0].slug, ))
573        return HttpResponseRedirect(url)
574
[d848b98]575
[f610262]576class MidwayAssignmentFilter(django_filters.FilterSet):
577    name = django_filters.CharFilter(name='group__name', lookup_type='icontains', label="Name contains")
578    abbreviation = django_filters.CharFilter(name='group__abbreviation', lookup_type='iexact', label="Abbreviation is")
579    activity_category = django_filters.ModelChoiceFilter(
580        label='Activity category',
581        name='group__activity_category',
582        queryset=groups.models.ActivityCategory.objects,
583    )
584
585    class Meta:
586        model = forms.models.MidwayAssignment
587        fields = [
588            'name',
589            'abbreviation',
590            'activity_category',
591        ]
592        order_by = (
593            ('group__name', 'Name', ),
594            ('group__abbreviation', 'Abbreviation', ),
595            ('group__activity_category__name', 'Activity category', ),
596            ('location', 'Location', ),
597        )
[d848b98]598
[1cfab5a]599
[d848b98]600class MidwayMapView(DetailView):
601    context_object_name = "midway"
602    model = forms.models.Midway
603    template_name = 'midway/map.html'
604
605    def get_context_data(self, **kwargs):
606        # Call the base implementation first to get a context
607        context = super(MidwayMapView, self).get_context_data(**kwargs)
608       
[f610262]609        filterset = MidwayAssignmentFilter(self.request.GET)
610        context['assignments'] = filterset.qs
611        context['filter'] = filterset
[7d7801f]612        context['pagename'] = 'midway'
[d848b98]613
614        return context
615
616
617class MidwayAssignmentsUploadForm(Form):
618    assignments = FileField()
619
[5e018d9]620@permission_required('forms.add_midwayassignment')
[d848b98]621def midway_assignment_upload(request, slug, ):
622    midway = get_object_or_404(forms.models.Midway, slug=slug, )
623
[7d7801f]624    uploaded = False
625    found = []
626    issues = collections.defaultdict(list)
627
[d848b98]628    if request.method == 'POST': # If the form has been submitted...
629        form = MidwayAssignmentsUploadForm(request.POST, request.FILES, ) # A form bound to the POST data
630
631        if form.is_valid(): # All validation rules pass
[7d7801f]632            uploaded = True
633            reader = csv.DictReader(request.FILES['assignments'])
634            for row in reader:
635                group_name = row['Group']
636                group_officers = row['officers']
637                table = row['Table']
638                issue = False
639                try:
640                    group = groups.models.Group.objects.get(name=group_name)
641                    assignment = forms.models.MidwayAssignment(
642                        midway=midway,
643                        location=table,
644                        group=group,
645                    )
646                    assignment.save()
647                    found.append(assignment)
648                    status = group.group_status.slug
649                    if status != 'active':
650                        issue = 'status=%s (added anyway)' % (status, )
651                except groups.models.Group.DoesNotExist:
652                    issue = 'unknown group (ignored)'
653                if issue:
654                    issues[issue].append((group_name, group_officers, table))
655            for issue in issues:
656                issues[issue] = sorted(issues[issue], key=lambda x: x[0])
657
[d848b98]658    else:
659        form = MidwayAssignmentsUploadForm() # An unbound form
660
661    context = {
662        'midway':midway,
663        'form':form,
[7d7801f]664        'uploaded': uploaded,
665        'found': found,
666        'issues': dict(issues),
[d848b98]667        'pagename':'midway',
668    }
669    return render_to_response('midway/upload.html', context, context_instance=RequestContext(request), )
Note: See TracBrowser for help on using the repository browser.