import forms.models import groups.models import groups.views import settings import util.emails from django.contrib.auth.decorators import user_passes_test, login_required, permission_required from django.views.generic import list_detail, ListView, DetailView from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext from django.template import Context, Template from django.template.loader import get_template from django.http import Http404, HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse from django.core.mail import EmailMessage, mail_admins from django.forms import Form from django.forms import ModelForm from django.forms import ModelChoiceField, ModelMultipleChoiceField from django.forms import ValidationError from django.db import connection from django.db.models import Q, Count import csv import datetime import StringIO ################# # GENERIC VIEWS # ################# class SelectGroupForm(Form): group = ModelChoiceField(queryset=groups.models.Group.objects.all()) def __init__(self, *args, **kwargs): queryset = None if 'queryset' in kwargs: queryset = kwargs['queryset'] del kwargs['queryset'] super(SelectGroupForm, self).__init__(*args, **kwargs) if queryset is not None: self.fields["group"].queryset = queryset def select_group(request, url_name_after, pagename='homepage', queryset=None, ): if request.method == 'POST': # If the form has been submitted... # A form bound to the POST data form = SelectGroupForm(request.POST, queryset=queryset, ) if form.is_valid(): # All validation rules pass group = form.cleaned_data['group'].id return HttpResponseRedirect(reverse(url_name_after, args=[group],)) # Redirect after POST else: form = SelectGroupForm(queryset=queryset, ) # An unbound form context = { 'form':form, 'pagename':pagename, } return render_to_response('forms/select.html', context, context_instance=RequestContext(request), ) ############################# # FIRST-YEAR SUMMER MAILING # ############################# @login_required def fysm_by_years(request, year, category, ): if year is None: year = datetime.date.today().year queryset = forms.models.FYSM.objects.filter(year=year).order_by('group__name') category_obj = None category_name = 'main' if category != None: category_obj = get_object_or_404(forms.models.FYSMCategory, slug=category) category_name = category_obj.name queryset = queryset.filter(categories=category_obj) forms.models.FYSMView.record_metric(request=request, fysm=None, year=year, page=category_name, ) categories = forms.models.FYSMCategory.objects.all() return list_detail.object_list( request, queryset=queryset, template_name="fysm/fysm_listing.html", template_object_name="fysm", extra_context={ "year": year, "pagename": "fysm", "category": category_obj, "categories": categories, } ) @login_required def fysm_view(request, year, submission, ): submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,) all = forms.models.FYSM.objects.only("id", "display_name", ) try: prev = all.filter(display_name__lt=submit_obj.display_name).order_by("-display_name")[0] except IndexError: prev = None try: next = all.filter(display_name__gt=submit_obj.display_name).order_by("display_name")[0] except IndexError: next = None forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page="detail", ) return list_detail.object_detail( request, forms.models.FYSM.objects, object_id=submission, template_name="fysm/fysm_detail.html", template_object_name="fysm", extra_context={ "year": year, "pagename": "fysm", "prev": prev, "next": next, }, ) def fysm_link(request, year, link_type, submission, ): submit_obj = get_object_or_404(forms.models.FYSM, pk=submission,) if submit_obj.year != int(year): raise Http404("Year mismatch: fysm.year='%s', request's year='%s'" % (submit_obj.year, year, )) if link_type == 'join': url = submit_obj.join_url elif link_type == 'website': url = submit_obj.website else: raise Http404("Unknown link type") forms.models.FYSMView.record_metric(request=request, fysm=submit_obj, year=year, page=link_type, ) return HttpResponseRedirect(url) def select_group_fysm(request, ): qobj = Q(activity_category__isnull = True) | ~(Q(activity_category__name='Dorm') | Q(activity_category__name='FSILG')) queryset = groups.models.Group.active_groups.filter(qobj) return select_group( request, url_name_after='fysm-manage', pagename='fysm', queryset=queryset, ) class FYSMRequestForm(ModelForm): class Meta: model = forms.models.FYSM fields = ( 'display_name', 'website', 'join_url', 'contact_email', 'description', 'logo', 'slide', 'tags', 'categories', ) def clean_display_name(self, ): name = self.cleaned_data['display_name'] if ',' in name: 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.""") return name def clean_description(self, ): description = self.cleaned_data['description'] length = len(description) if length > 400: raise ValidationError("Descriptions are capped at 400 characters, and this one is %d characters." % (length, )) return description @login_required def fysm_manage(request, group, ): year = datetime.date.today().year group_obj = get_object_or_404(groups.models.Group, pk=group) initial = {} try: fysm_obj = forms.models.FYSM.objects.get(group=group_obj, year=year, ) print "Successfully found", fysm_obj.__dict__ except forms.models.FYSM.DoesNotExist: fysm_obj = forms.models.FYSM() fysm_obj.group = group_obj fysm_obj.year = year initial['display_name'] = group_obj.name initial['year'] = year initial['website'] = group_obj.website_url initial['join_url'] = group_obj.website_url initial['contact_email'] = group_obj.officer_email if request.method == 'POST': # If the form has been submitted... form = FYSMRequestForm(request.POST, request.FILES, instance=fysm_obj, ) # A form bound to the POST data if form.is_valid(): # All validation rules pass request_obj = form.save() view_path = reverse('fysm-view', args=[year, request_obj.pk, ]) view_uri = '%s://%s%s' % (request.is_secure() and 'https' or 'http', request.get_host(), view_path) # Send email email = util.emails.email_from_template( tmpl='fysm/update_email.txt', context = Context({ 'group': group_obj, 'fysm': fysm_obj, 'view_uri': view_uri, 'submitter': request.user, 'request': request, 'sender': "ASA FYSM team", }), subject='FYSM entry for "%s" updated by "%s"' % ( group_obj.name, request.user, ), to=[group_obj.officer_email, request.user.email, ], from_email='asa-fysm@mit.edu', ) email.bcc = ['asa-fysm-submissions@mit.edu'] email.send() return HttpResponseRedirect(reverse('fysm-thanks', args=[fysm_obj.pk],)) # Redirect after POST else: form = FYSMRequestForm(instance=fysm_obj, initial=initial, ) # An unbound form context = { 'group':group_obj, 'fysm':fysm_obj, 'form':form, 'categories':forms.models.FYSMCategory.objects.all(), 'pagename':'fysm', } return render_to_response('fysm/submit.html', context, context_instance=RequestContext(request), ) def fysm_thanks(request, fysm, ): year = datetime.date.today().year fysm_obj = get_object_or_404(forms.models.FYSM, pk=fysm) context = { 'group':fysm_obj.group, 'fysm':fysm_obj, 'pagename':'fysm', } return render_to_response('fysm/thanks.html', context, context_instance=RequestContext(request), ) ##################### # Membership update # ##################### membership_update_qs = groups.models.Group.objects.filter(group_status__slug__in=['active', 'suspended', ]) class Form_GroupMembershipUpdate(ModelForm): group = ModelChoiceField(queryset=membership_update_qs) def __init__(self, *args, **kwargs): super(Form_GroupMembershipUpdate, self).__init__(*args, **kwargs) self.fields['no_hazing'].required = True class Meta: model = forms.models.GroupMembershipUpdate fields = [ 'group', 'updater_title', 'group_email', 'officer_email', 'email_preface', 'no_hazing', 'no_discrimination', 'membership_definition', 'num_undergrads', 'num_grads', 'num_alum', 'num_other_affiliate', 'num_other', 'membership_list', ] @login_required def group_membership_update(request, ): year = datetime.date.today().year initial = { } update_obj = forms.models.GroupMembershipUpdate() update_obj.update_time = datetime.datetime.now() update_obj.updater_name = request.user.username confirm_path = reverse('membership-confirm', ) confirm_uri = '%s://%s%s' % (request.is_secure() and 'https' or 'http', request.get_host(), confirm_path) if request.method == 'POST': # If the form has been submitted... form = Form_GroupMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data if form.is_valid(): # All validation rules pass request_obj = form.save() group_obj = request_obj.group # Send email tmpl = get_template('membership/anti-hazing.txt') ctx = Context({ 'update': request_obj, 'group': group_obj, 'submitter': request.user, }) body = tmpl.render(ctx) email = EmailMessage( subject='Anti-Hazing and Non-Discrimination Acknowledgement for %s' % ( group_obj.name, ), body=body, from_email=request.user.email, to=[request_obj.group_email, ], cc=[request_obj.officer_email, ], bcc=['asa-db-outgoing@mit.edu', ], ) email.send() # Send email tmpl = get_template('membership/submit-confirm-email.txt') ctx = Context({ 'update': request_obj, 'group': group_obj, 'submitter': request.user, 'confirm_uri': confirm_uri, }) body = tmpl.render(ctx) email = EmailMessage( subject='ASA Membership Information for %s' % ( group_obj.name, ), body=body, from_email=request.user.email, to=[request_obj.officer_email, ], bcc=['asa-db-outgoing@mit.edu', ], ) email.send() return HttpResponseRedirect(reverse('membership-thanks', )) # Redirect after POST else: form = Form_GroupMembershipUpdate(initial=initial, ) # An unbound form context = { 'form':form, 'confirm_uri': confirm_uri, 'pagename':'groups', } return render_to_response('membership/update.html', context, context_instance=RequestContext(request), ) class Form_PersonMembershipUpdate(ModelForm): groups = ModelMultipleChoiceField(queryset=membership_update_qs) class Meta: model = forms.models.PersonMembershipUpdate fields = [ 'groups', ] @login_required def person_membership_update(request, ): year = datetime.date.today().year initial = { } cycle = forms.models.GroupConfirmationCycle.latest() try: update_obj = forms.models.PersonMembershipUpdate.objects.get( username=request.user.username, deleted__isnull=True, cycle=cycle, ) selected_groups = update_obj.groups.all() print "Got update" except forms.models.PersonMembershipUpdate.DoesNotExist: update_obj = forms.models.PersonMembershipUpdate() update_obj.update_time = datetime.datetime.now() update_obj.username = request.user.username update_obj.cycle = cycle selected_groups = [] accounts = groups.models.AthenaMoiraAccount try: person = accounts.active_accounts.get(username=request.user.username) if person.is_student(): update_obj.valid = forms.models.VALID_AUTOVALIDATED else: update_obj.valid = forms.models.VALID_AUTOREJECTED except accounts.DoesNotExist: pass update_obj.valid = forms.models.VALID_AUTOREJECTED update_obj.save() filterset = groups.views.GroupFilter(request.GET, membership_update_qs) filtered_groups = filterset.qs.all() show_filtered_groups = ('search' in request.GET) message = "" message_type = "info" if request.method == 'POST' and 'add-remove' in request.POST: group = groups.models.Group.objects.get(id=request.POST['group']) if request.POST['action'] == 'remove': if group in update_obj.groups.all(): update_obj.groups.remove(group) message = "You have been successfully removed from %s." % (group, ) else: message = "Sorry, but you're not in %s." % (group, ) message_type = "warn" elif request.POST['action'] == 'add': if group in update_obj.groups.all(): message = "Sorry, but you're already in %s." % (group, ) message_type = "warn" else: update_obj.groups.add(group) message = "You have been successfully added to %s." % (group, ) else: message = "Uh, somehow you tried to do something besides adding and removing..." message_type = "alert" if request.method == 'POST' and 'list' in request.POST: # If the form has been submitted... form = Form_PersonMembershipUpdate(request.POST, request.FILES, instance=update_obj) # A form bound to the POST data if form.is_valid(): # All validation rules pass request_obj = form.save() message = "Update saved" else: form = Form_PersonMembershipUpdate(initial=initial, instance=update_obj, ) # An unbound form context = { 'form':form, 'filter':filterset, 'show_filtered_groups':show_filtered_groups, 'filtered_groups':filtered_groups, 'member_groups':selected_groups, 'message': message, 'message_type': message_type, 'pagename':'groups', } return render_to_response('membership/confirm.html', context, context_instance=RequestContext(request), ) class View_GroupMembershipList(ListView): context_object_name = "group_list" template_name = "membership/submitted.html" def get_queryset(self): group_updates = forms.models.GroupMembershipUpdate.objects.all() group_updates = group_updates.filter( group__personmembershipupdate__deleted__isnull=True, group__personmembershipupdate__valid__gt=0, ) group_updates = group_updates.annotate(num_confirms=Count('group__personmembershipupdate')) #print len(list(group_updates)) #for query in connection.queries: print query return group_updates @permission_required('groups.view_group_private_info') def group_confirmation_issues(request, ): active_groups = groups.models.Group.active_groups group_updates = forms.models.GroupMembershipUpdate.objects.all() people_confirmations = forms.models.PersonMembershipUpdate.objects.filter( deleted__isnull=True, valid__gt=0, ) buf = StringIO.StringIO() output = csv.writer(buf) output.writerow(['group_id', 'group_name', 'issue', 'num_confirm', 'officer_email', ]) q_present = Q(id__in=group_updates.values('group')) missing_groups = active_groups.filter(~q_present) #print len(list(group_updates)) for group in missing_groups: num_confirms = len(people_confirmations.filter(groups=group)) output.writerow([ group.id, group.name, 'unsubmitted', num_confirms, group.officer_email, ]) for group_update in group_updates: group = group_update.group num_confirms = len(people_confirmations.filter(groups=group)) if num_confirms < 5: output.writerow([ group.id, group.name, 'confirmations', num_confirms, group.officer_email, ]) return HttpResponse(buf.getvalue(), mimetype='text/plain', )