Merge branch 'chrisjrn/20161014-b'

Fixes #63
This commit is contained in:
Christopher Neugebauer 2016-10-14 16:52:59 -07:00
commit c76c0f6f4b
3 changed files with 120 additions and 32 deletions

View file

@ -1,6 +1,10 @@
import csv
import forms
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.shortcuts import render from django.shortcuts import render
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse
from functools import wraps from functools import wraps
from registrasion import views from registrasion import views
@ -194,44 +198,114 @@ def report_view(title, form_type=None):
''' '''
# Create & return view
def _report(view): def _report(view):
report_view = ReportView(view, title, form_type)
@wraps(view) report_view = user_passes_test(views._staff_only)(report_view)
@user_passes_test(views._staff_only) report_view = wraps(view)(report_view)
def inner_view(request, *a, **k):
if form_type is not None:
form = form_type(request.GET)
form.is_valid()
else:
form = None
reports = view(request, form, *a, **k)
if isinstance(reports, Report):
reports = [reports]
reports = [
_ReportTemplateWrapper("text/html", report)
for report in reports
]
ctx = {
"title": title,
"form": form,
"reports": reports,
}
return render(request, "registrasion/report.html", ctx)
# Add this report to the list of reports. # Add this report to the list of reports.
_all_report_views.append(inner_view) _all_report_views.append(report_view)
return report_view
# Return the callable
return inner_view
return _report return _report
class ReportView(object):
def __init__(self, inner_view, title, form_type):
# Consolidate form_type so it has content type and section
self.inner_view = inner_view
self.title = title
self.form_type = form_type
def __call__(self, request, *a, **k):
data = ReportViewRequestData(self, request, *a, **k)
return self.render(data)
def get_form(self, request):
# Create a form instance
if self.form_type is not None:
form = self.form_type(request.GET)
# Pre-validate it
form.is_valid()
else:
form = None
return form
@classmethod
def wrap_reports(cls, reports, content_type):
reports = [
_ReportTemplateWrapper(content_type, report)
for report in reports
]
return reports
def render(self, data):
renderers = {
"text/csv": self._render_as_csv,
"text/html": self._render_as_html,
None: self._render_as_html,
}
render = renderers[data.content_type]
return render(data)
def _render_as_html(self, data):
ctx = {
"title": self.title,
"form": data.form,
"reports": data.reports,
}
return render(data.request, "registrasion/report.html", ctx)
def _render_as_csv(self, data):
report = data.reports[data.section]
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(content_type='text/csv')
writer = csv.writer(response)
encode = lambda i: i.encode("utf8") if isinstance(i, unicode) else i
writer.writerow(list(encode(i) for i in report.headings()))
for row in report.rows():
writer.writerow(list(encode(i) for i in row))
return response
class ReportViewRequestData(object):
def __init__(self, report_view, request, *a, **k):
self.report_view = report_view
self.request = request
# Calculate other data
self.form = report_view.get_form(request)
# Content type and section come from request.GET
self.content_type = request.GET.get("content_type")
self.section = request.GET.get("section")
self.section = int(self.section) if self.section else None
# Reports come from calling the inner view
reports = report_view.inner_view(request, self.form, *a, **k)
# Normalise to a list
if isinstance(reports, Report):
reports = [reports]
# Wrap them in appropriate format
reports = ReportView.wrap_reports(reports, self.content_type)
self.reports = reports
def get_all_reports(): def get_all_reports():
''' Returns all the views that have been registered with @report ''' ''' Returns all the views that have been registered with @report '''

View file

@ -408,7 +408,7 @@ def attendee(request, form, user_id=None):
''' Returns a list of all manifested attendees if no attendee is specified, ''' Returns a list of all manifested attendees if no attendee is specified,
else displays the attendee manifest. ''' else displays the attendee manifest. '''
if user_id is None and not form.has_changed(): if user_id is None:
return attendee_list(request) return attendee_list(request)
if form.cleaned_data["user"] is not None: if form.cleaned_data["user"] is not None:

View file

@ -4,6 +4,7 @@ from registrasion.controllers.item import ItemController
from django import template from django import template
from django.db.models import Sum from django.db.models import Sum
from urllib import urlencode
register = template.Library() register = template.Library()
@ -74,3 +75,16 @@ def items_purchased(context, category=None):
return ItemController(context.request.user).items_purchased( return ItemController(context.request.user).items_purchased(
category=category category=category
) )
@register.assignment_tag(takes_context=True)
def report_as_csv(context, section):
old_query = context.request.META["QUERY_STRING"]
query = dict([("section", section), ("content_type", "text/csv")])
querystring = urlencode(query)
if old_query:
querystring = old_query + "&" + querystring
return context.request.path + "?" + querystring