source: asadb/forms/views.py

stablestage
Last change on this file was 9605a6a, checked in by Alex Dehnert <adehnert@…>, 12 years ago

Add missing column heading (ASA-#258)

  • Property mode set to 100644
File size: 26.9 KB
Line 
1import collections
2import csv
3import datetime
4import StringIO
5
6from django.conf import settings
7from django.contrib.auth.decorators import user_passes_test, login_required, permission_required
8from django.core.exceptions import PermissionDenied
9from django.views.generic import list_detail, ListView, DetailView
10from django.shortcuts import render_to_response, get_object_or_404
11from django.template import RequestContext
12from django.template import Context, Template
13from django.template.loader import get_template
14from django.http import Http404, HttpResponseRedirect, HttpResponse
15from django.core.urlresolvers import reverse
16from django.core.mail import EmailMessage, mail_admins
17from django.forms import FileField
18from django.forms import Form
19from django.forms import ModelForm
20from django.forms import ModelChoiceField, ModelMultipleChoiceField
21from django.forms import ValidationError
22from django.db import connection
23from django.db.models import Q, Count
24
25import django_filters
26
27import forms.models
28import groups.models
29import groups.views
30import util.emails
31
32#################
33# GENERIC VIEWS #
34#################
35
36class SelectGroupForm(Form):
37    group = ModelChoiceField(queryset=groups.models.Group.objects.all())
38    def __init__(self, *args, **kwargs):
39        queryset = None
40        if 'queryset' in kwargs:
41            queryset = kwargs['queryset']
42            del kwargs['queryset']
43        super(SelectGroupForm, self).__init__(*args, **kwargs)
44        if queryset is not None:
45            self.fields["group"].queryset = queryset
46
47def select_group(request, url_name_after, url_args=[], pagename='homepage', queryset=None, title="", msg=""):
48    if request.method == 'POST': # If the form has been submitted...
49        # A form bound to the POST data
50        form = SelectGroupForm(request.POST, queryset=queryset, )
51        if form.is_valid(): # All validation rules pass
52            group = form.cleaned_data['group'].id
53            return HttpResponseRedirect(reverse(url_name_after, args=url_args+[group],)) # Redirect after POST
54    else:
55        form = SelectGroupForm(queryset=queryset, ) # An unbound form
56
57    if not title: title = "Select group"
58    context = {
59        'form':form,
60        'title':title,
61        'msg':msg,
62        'pagename':pagename,
63    }
64    return render_to_response('forms/select.html', context, context_instance=RequestContext(request), )
65
66#############################
67# FIRST-YEAR SUMMER MAILING #
68#############################
69
70@login_required
71def fysm_by_years(request, year, category, ):
72    if year is None: year = datetime.date.today().year
73    queryset = forms.models.FYSM.objects.filter(year=year).order_by('group__name')
74    category_obj = None
75    category_name = 'main'
76    if category != None:
77        category_obj = get_object_or_404(forms.models.FYSMCategory, slug=category)
78        category_name = category_obj.name
79        queryset = queryset.filter(categories=category_obj)
80    forms.models.FYSMView.record_metric(request=request, fysm=None, year=year, page=category_name, )
81    categories = forms.models.FYSMCategory.objects.all()
82    return list_detail.object_list(
83        request,
84        queryset=queryset,
85        template_name="fysm/fysm_listing.html",
86        template_object_name="fysm",
87        extra_context={
88            "year": year,
89            "pagename": "fysm",
90            "category": category_obj,
91            "categories": categories,
92        }
93    )
94
95@login_required
96def fysm_view(request, year, submission, ):
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
107    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page="detail", )
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",
117            "prev": prev,
118            "next": next,
119        },
120    )
121
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")
132    forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page=link_type, )
133    return HttpResponseRedirect(url)
134
135def select_group_fysm(request, ):
136    qobj = Q(activity_category__isnull = True) | ~(Q(activity_category__name='Dorm') | Q(activity_category__name='FSILG'))
137    queryset = groups.models.Group.active_groups.filter(qobj)
138    return select_group(
139        request,
140        url_name_after='fysm-manage',
141        pagename='fysm',
142        queryset=queryset,
143    )
144
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',
155            'tags',
156            'categories',
157        )
158
159    def clean_display_name(self, ):
160        name = self.cleaned_data['display_name']
161        if ',' in name:
162            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.""")
163        return name
164
165    def clean_description(self, ):
166        description = self.cleaned_data['description']
167        length = len(description)
168        if length > 400:
169            raise ValidationError("Descriptions are capped at 400 characters, and this one is %d characters." % (length, ))
170        return description
171
172@login_required
173def fysm_manage(request, group, ):
174    year = datetime.date.today().year
175    group_obj = get_object_or_404(groups.models.Group, pk=group)
176
177    initial = {}
178    try:
179        fysm_obj = forms.models.FYSM.objects.get(group=group_obj, year=year, )
180    except forms.models.FYSM.DoesNotExist:
181        fysm_obj = forms.models.FYSM()
182        fysm_obj.group = group_obj
183        fysm_obj.year = year
184        initial['display_name'] = group_obj.name
185        initial['year'] = year
186        initial['website'] = group_obj.website_url
187        initial['join_url'] = group_obj.website_url
188        initial['contact_email'] = group_obj.officer_email
189
190    if request.method == 'POST': # If the form has been submitted...
191        form = FYSMRequestForm(request.POST, request.FILES, instance=fysm_obj, ) # A form bound to the POST data
192
193        if form.is_valid(): # All validation rules pass
194            request_obj = form.save()
195
196            view_uri = request.build_absolute_uri(reverse('fysm-view', args=[year, request_obj.pk, ]))
197
198            # Send email
199            email = util.emails.email_from_template(
200                tmpl='fysm/update_email.txt',
201                context = Context({
202                    'group': group_obj,
203                    'fysm': fysm_obj,
204                    'view_uri': view_uri,
205                    'submitter': request.user,
206                    'request': request,
207                    'sender': "ASA FYSM team",
208                }),
209                subject='FYSM entry for "%s" updated by "%s"' % (
210                    group_obj.name,
211                    request.user,
212                ),
213                to=[group_obj.officer_email, request.user.email, ],
214                from_email='asa-fysm@mit.edu',
215            )
216            email.bcc = ['asa-fysm-submissions@mit.edu']
217            email.send()
218            return HttpResponseRedirect(reverse('fysm-thanks', args=[fysm_obj.pk],)) # Redirect after POST
219
220    else:
221        form = FYSMRequestForm(instance=fysm_obj, initial=initial, ) # An unbound form
222
223    context = {
224        'group':group_obj,
225        'fysm':fysm_obj,
226        'form':form,
227        'categories':forms.models.FYSMCategory.objects.all(),
228        'pagename':'fysm',
229    }
230    return render_to_response('fysm/submit.html', context, context_instance=RequestContext(request), )
231
232
233def fysm_thanks(request, fysm, ):
234    year = datetime.date.today().year
235    fysm_obj = get_object_or_404(forms.models.FYSM, pk=fysm)
236
237    context = {
238        'group':fysm_obj.group,
239        'fysm':fysm_obj,
240        'pagename':'fysm',
241    }
242    return render_to_response('fysm/thanks.html', context, context_instance=RequestContext(request), )
243
244#####################
245# Membership update #
246#####################
247
248membership_update_qs = groups.models.Group.objects.filter(group_status__slug__in=['active', 'suspended', ])
249
250@login_required
251def group_membership_update_select_group(request, ):
252    cycle = forms.models.GroupConfirmationCycle.latest()
253
254    users_groups = groups.models.Group.admin_groups(request.user.username)
255    qs = membership_update_qs.filter(pk__in=users_groups)
256
257    return select_group(request=request,
258        url_name_after='membership-update-group',
259        url_args=[cycle.slug],
260        pagename='groups',
261        queryset=qs,
262        title="Submit membership update for...",
263    )
264
265class Form_GroupMembershipUpdate(ModelForm):
266    def __init__(self, *args, **kwargs):
267        super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs)
268        self.fields['no_hazing'].required = True
269        help_text = "If you have a membership list, you can get help turning it into membership breakdown using our <a href='%s'>people lookup</a> tool. You'll need to copy the numbers back over, though." % (reverse('membership-people-lookup'), )
270        self.fields['num_undergrads'].help_text = help_text
271
272    class Meta:
273        model = forms.models.GroupMembershipUpdate
274        fields = [
275            'updater_title',
276            'group_email',
277            'officer_email',
278            'email_preface',
279            'no_hazing',
280            'no_discrimination',
281            'membership_definition',
282            'num_undergrads',
283            'num_grads',
284            'num_alum',
285            'num_other_affiliate',
286            'num_other',
287            #'membership_list',
288        ]
289
290@login_required
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
301
302    confirm_uri = request.build_absolute_uri(reverse('membership-confirm'))
303    submitted_uri = request.build_absolute_uri(reverse('membership-submitted'))
304
305    if request.method == 'POST':
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
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
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(
325                subject='Anti-Hazing and Non-Discrimination Acknowledgement for %s' % (
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, ],
332                bcc=['asa-db-outgoing@mit.edu', ],
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,
343                'submitted_uri': submitted_uri,
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, ],
353                bcc=['asa-db-outgoing@mit.edu', ],
354            )
355            email.send()
356
357            return HttpResponseRedirect(reverse('membership-thanks', )) # Redirect after POST
358
359    else:
360        form = Form_GroupMembershipUpdate(instance=update_obj)
361
362    context = {
363        'form':form,
364        'group':group_obj,
365        'cycle':cycle,
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):
372    groups = ModelMultipleChoiceField(queryset=membership_update_qs)
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    }
383    cycle = forms.models.GroupConfirmationCycle.latest()
384
385    # Initialize/find the PersonMembershipUpdate for this user
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
400    # Determine whether the submitter is a student or not
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
412    update_obj.save()
413
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    message = ""
423    message_type = "info"
424
425    if update_obj.valid <= forms.models.VALID_UNSET:
426        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."
427        message_type = "warn"
428
429    # Handle the single group add/remove forms
430    # * removing previously confirmed groups
431    # * add/remove groups that list the user in a role
432    # * add/remove groups the user searched for
433    if request.method == 'POST' and 'add-remove' in request.POST:
434        group = groups.models.Group.objects.get(id=request.POST['group'])
435        if request.POST['action'] == 'remove':
436            if group in update_obj.groups.all():
437                update_obj.groups.remove(group)
438                message = "You have successfully unconfirmed membership in %s." % (group, )
439            else:
440                message = "Removal failed because you had not confirmed membership in %s." % (group, )
441                message_type = "warn"
442        elif request.POST['action'] == 'add':
443            if group in update_obj.groups.all():
444                message = "Membership in %s already confirmed." % (group, )
445                message_type = "warn"
446            else:
447                update_obj.groups.add(group)
448                message = "You have successfully confirmed membership in %s." % (group, )
449        else:
450            message = "Uh, somehow you tried to do something besides adding and removing..."
451            message_type = "alert"
452
453    # Handle the big list of groups
454    if request.method == 'POST' and 'list' in request.POST:
455        form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj)
456        if form.is_valid():
457            request_obj = form.save()
458            message = "Update saved"
459    else:
460        form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, )
461    form.fields['groups'].widget.attrs['size'] = 20
462
463    # Render the page
464    context = {
465        'role_groups':role_groups,
466        'form':form,
467        'member_groups':selected_groups,
468        'message': message,
469        'message_type': message_type,
470        'pagename':'groups',
471    }
472    return render_to_response('membership/confirm.html', context, context_instance=RequestContext(request), )
473
474
475class View_GroupMembershipList(ListView):
476    context_object_name = "group_list"
477    template_name = "membership/submitted.html"
478
479    def get_queryset(self):
480        cycle = forms.models.GroupConfirmationCycle.latest()
481        group_updates = forms.models.GroupMembershipUpdate.objects.all()
482        group_updates = group_updates.filter(
483            cycle=cycle,
484            group__personmembershipupdate__cycle=cycle,
485            group__personmembershipupdate__deleted__isnull=True,
486            group__personmembershipupdate__valid__gt=0,
487        )
488        group_updates = group_updates.annotate(num_confirms=Count('group__personmembershipupdate'))
489        #print len(list(group_updates))
490        #for query in connection.queries: print query
491        return group_updates
492
493
494class View_GroupConfirmationCyclesList(ListView):
495    context_object_name = "cycle_list"
496    template_name = "membership/admin.html"
497    model = forms.models.GroupConfirmationCycle
498
499    def get_context_data(self, **kwargs):
500        context = super(View_GroupConfirmationCyclesList, self).get_context_data(**kwargs)
501        context['pagename'] = 'groups'
502        return context
503
504
505@permission_required('groups.view_group_private_info')
506def group_confirmation_issues(request, slug, ):
507    account_numbers = ("accounts" in request.GET) and request.GET['accounts'] == "1"
508
509    check_groups = groups.models.Group.objects.filter(group_status__slug__in=('active', 'suspended', ))
510    check_groups = check_groups.select_related('group_status')
511    group_updates = forms.models.GroupMembershipUpdate.objects.filter(cycle__slug=slug, )
512    group_updates = group_updates.select_related('group', 'group__group_status')
513    people_confirmations = forms.models.PersonMembershipUpdate.objects.filter(
514        deleted__isnull=True,
515        valid__gt=0,
516        cycle__slug=slug,
517    )
518
519    buf = StringIO.StringIO()
520    output = csv.writer(buf)
521    fields = ['group_id', 'group_name', 'group_status', 'recognition_date', 'issue', 'num_confirm', 'officer_email', ]
522    if account_numbers: fields.append("main_account")
523    output.writerow(fields)
524
525    def output_issue(group, issue, num_confirms):
526        fields = [
527            group.id,
528            group.name,
529            group.group_status.slug,
530            group.recognition_date,
531            issue,
532            num_confirms,
533            group.officer_email,
534        ]
535        if account_numbers: fields.append(group.main_account_id)
536        output.writerow(fields)
537
538    q_present = Q(id__in=group_updates.values('group'))
539    missing_groups = check_groups.filter(~q_present)
540    #print len(list(group_updates))
541    for group in missing_groups:
542        #num_confirms = len(people_confirmations.filter(groups=group))
543        output_issue(group, 'unsubmitted', '')
544
545    for group_update in group_updates:
546        group = group_update.group
547        num_confirms = people_confirmations.filter(groups=group).count()
548        problems = []
549
550        if num_confirms < 5:
551            problems.append("confirmations")
552
553        num_students = group_update.num_undergrads + group_update.num_grads
554        num_other = group_update.num_alum + group_update.num_other_affiliate + group_update.num_other
555        if num_students < num_other:
556            problems.append("50%")
557
558        for problem in problems:
559            output_issue(group, problem, num_confirms)
560
561    return HttpResponse(buf.getvalue(), mimetype='text/csv', )
562
563
564class PeopleStatusLookupForm(ModelForm):
565    class Meta:
566        model = forms.models.PeopleStatusLookup
567        fields = ('people', )
568
569def people_status_lookup(request, pk=None, ):
570    if pk is None:
571        if request.method == 'POST':
572            form = PeopleStatusLookupForm(request.POST, request.FILES, )
573            if form.is_valid(): # All validation rules pass
574                lookup = form.save(commit=False)
575                lookup.requestor = request.user
576                lookup.referer = request.META['HTTP_REFERER']
577                lookup.update_classified_people()
578                results = lookup.classifications_with_descriptions()
579                lookup.save()
580        else:
581            form = PeopleStatusLookupForm()
582            results = None
583    else:
584        if request.user.has_perm('forms.view_peoplestatusupdate'):
585            lookup = get_object_or_404(forms.models.PeopleStatusLookup, pk=int(pk))
586            results = lookup.classifications_with_descriptions()
587            form = None
588        else:
589            raise PermissionDenied("You don't have permission to view old lookup requests.")
590
591    context = {
592        'form': form,
593        'results': results,
594    }
595
596    return render_to_response('membership/people-lookup.html', context, context_instance=RequestContext(request), )
597
598##########
599# Midway #
600##########
601
602
603class View_Midways(ListView):
604    context_object_name = "midway_list"
605    template_name = "midway/midway_list.html"
606
607    def get_queryset(self):
608        midways = forms.models.Midway.objects.order_by('date')
609        return midways
610
611    def get_context_data(self, **kwargs):
612        context = super(View_Midways, self).get_context_data(**kwargs)
613        context['pagename'] = 'midway'
614        return context
615
616def midway_map_latest(request, ):
617    midways = forms.models.Midway.objects.order_by('-date')[:1]
618    if len(midways) == 0:
619        raise Http404("No midways found.")
620    else:
621        url = reverse('midway-map', args=(midways[0].slug, ))
622        return HttpResponseRedirect(url)
623
624
625class MidwayAssignmentFilter(django_filters.FilterSet):
626    name = django_filters.CharFilter(name='group__name', lookup_type='icontains', label="Name contains")
627    abbreviation = django_filters.CharFilter(name='group__abbreviation', lookup_type='iexact', label="Abbreviation is")
628    activity_category = django_filters.ModelChoiceFilter(
629        label='Activity category',
630        name='group__activity_category',
631        queryset=groups.models.ActivityCategory.objects,
632    )
633
634    class Meta:
635        model = forms.models.MidwayAssignment
636        fields = [
637            'name',
638            'abbreviation',
639            'activity_category',
640        ]
641        order_by = (
642            ('group__name', 'Name', ),
643            ('group__abbreviation', 'Abbreviation', ),
644            ('group__activity_category__name', 'Activity category', ),
645            ('location', 'Location', ),
646        )
647
648
649class MidwayMapView(DetailView):
650    context_object_name = "midway"
651    model = forms.models.Midway
652    template_name = 'midway/map.html'
653
654    def get_context_data(self, **kwargs):
655        # Call the base implementation first to get a context
656        context = super(MidwayMapView, self).get_context_data(**kwargs)
657       
658        filterset = MidwayAssignmentFilter(self.request.GET)
659        context['assignments'] = filterset.qs
660        context['filter'] = filterset
661        context['pagename'] = 'midway'
662
663        return context
664
665
666class MidwayAssignmentsUploadForm(Form):
667    def validate_csv_fields(upload_file):
668        reader = csv.reader(upload_file)
669        row = reader.next()
670        for col in ('Group', 'officers', 'Table', ):
671            if col not in row:
672                raise ValidationError('Please upload a CSV file with (at least) columns "Group", "officers", and "Table". (Missing at least "%s".)' % (col, ))
673
674    assignments = FileField(validators=[validate_csv_fields])
675
676@permission_required('forms.add_midwayassignment')
677def midway_assignment_upload(request, slug, ):
678    midway = get_object_or_404(forms.models.Midway, slug=slug, )
679
680    uploaded = False
681    found = []
682    issues = collections.defaultdict(list)
683
684    if request.method == 'POST': # If the form has been submitted...
685        form = MidwayAssignmentsUploadForm(request.POST, request.FILES, ) # A form bound to the POST data
686
687        if form.is_valid(): # All validation rules pass
688            uploaded = True
689            reader = csv.DictReader(request.FILES['assignments'])
690            for row in reader:
691                group_name = row['Group']
692                group_officers = row['officers']
693                table = row['Table']
694                issue = False
695                try:
696                    group = groups.models.Group.objects.get(name=group_name)
697                    assignment = forms.models.MidwayAssignment(
698                        midway=midway,
699                        location=table,
700                        group=group,
701                    )
702                    assignment.save()
703                    found.append(assignment)
704                    status = group.group_status.slug
705                    if status != 'active':
706                        issue = 'status=%s (added anyway)' % (status, )
707                except groups.models.Group.DoesNotExist:
708                    issue = 'unknown group (ignored)'
709                except groups.models.Group.MultipleObjectsReturned:
710                    issue = 'multiple groups found (ignored)'
711                if issue:
712                    issues[issue].append((group_name, group_officers, table))
713            for issue in issues:
714                issues[issue] = sorted(issues[issue], key=lambda x: x[0])
715
716    else:
717        form = MidwayAssignmentsUploadForm() # An unbound form
718
719    context = {
720        'midway':midway,
721        'form':form,
722        'uploaded': uploaded,
723        'found': found,
724        'issues': dict(issues),
725        'pagename':'midway',
726    }
727    return render_to_response('midway/upload.html', context, context_instance=RequestContext(request), )
Note: See TracBrowser for help on using the repository browser.