You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

263 lines
9.6 KiB

import datetime
from functools import update_wrapper
from django.contrib import admin, messages
from django.contrib.admin.helpers import AdminErrorList, AdminForm
from django.contrib.auth import get_permission_codename
from django.contrib.auth.admin import csrf_protect_m
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.shortcuts import redirect
from django.template.defaultfilters import slugify, yesno
from django.template.response import TemplateResponse
from django.utils import timezone
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from tablib import Dataset
from .conf import settings
from .forms import SubmissionExportForm
from .models import Form, FormSubmission
try:
from django.contrib.admin.utils import unquote
except ImportError:
from django.contrib.admin.util import unquote
try:
from django.http import JsonResponse
except ImportError:
from .compat import JsonResponse
class FormFilter(admin.SimpleListFilter):
title = _('Forms')
parameter_name = 'form'
def lookups(self, request, model_admin):
forms = Form.active_objects.all()
for obj in forms:
yield (
str(obj.id), u'%s (%s)' % (obj.name, obj.submission_count)
)
def queryset(self, request, queryset):
if self.value():
return queryset.filter(plugin_id=self.value())
class FormSubmissionAdmin(admin.ModelAdmin):
change_form_template = 'admin/djangocms_forms/formsubmission/change_form.html'
change_list_template = 'admin/djangocms_forms/formsubmission/change_list.html'
export_form_template = 'admin/djangocms_forms/formsubmission/export_form.html'
list_display = ('plugin', 'creation_date_display', 'created_by', 'ip', 'referrer', )
list_filter = (FormFilter, )
readonly_fields = ('creation_date_display', 'created_by', 'plugin', 'ip', 'referrer', )
date_hierarchy = 'creation_date'
fieldsets = (
(None, {
'fields': ('creation_date_display', 'created_by', 'ip', 'referrer', )
}),
)
class Media:
js = (
'js/djangocms_forms/admin/jquery-form-export.js',
)
def has_add_permission(self, request):
return False
def has_export_permission(self, request):
opts = self.opts
codename = get_permission_codename('export', opts)
return request.user.has_perm('%s.%s' % (opts.app_label, codename))
def creation_date_display(self, obj):
return obj.creation_date.strftime(settings.DJANGOCMS_FORMS_DATETIME_FORMAT)
creation_date_display.short_description = _('Sent On')
def get_queryset(self, request):
qs = super(FormSubmissionAdmin, self).get_queryset(request)
return qs.select_related('created_by', 'plugin', )
def get_urls(self):
"""
Add the export view to urls.
"""
urls = super(FormSubmissionAdmin, self).get_urls()
from django.conf.urls import patterns, url
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)
info = self.model._meta.app_label, self.model._meta.model_name
extra_urls = patterns(
'',
url(r'^export/$', wrap(self.export_view), name='%s_%s_export' % info),
)
return extra_urls + urls
@csrf_protect_m
def changelist_view(self, request, extra_context=None):
context = extra_context or {}
context.update({
'title': self.opts.verbose_name_plural.title(),
'has_export_permission': self.has_export_permission(request),
})
return super(FormSubmissionAdmin, self).changelist_view(
request, extra_context=context)
def change_view(self, request, object_id, form_url='', extra_context=None):
context = extra_context or {}
obj = self.get_object(request, unquote(object_id))
if obj:
context.update({
'title': force_text(obj.plugin),
})
return super(FormSubmissionAdmin, self).change_view(
request, object_id, form_url=form_url,
extra_context=context)
def export_view(self, request, form_url=''):
"""The 'export' admin view for this model."""
info = self.opts.app_label, self.opts.model_name
if not self.has_export_permission(request):
raise PermissionDenied
form = SubmissionExportForm(data=request.POST if request.method == 'POST' else None)
if form.is_valid():
data = form.cleaned_data
queryset = self.get_queryset(request) \
.filter(plugin_id=data.get('form')) \
.select_related('created_by', 'plugin', )
from_date, to_date = data.get('from_date'), data.get('to_date')
headers = data.get('headers', [])
if from_date:
queryset = queryset.filter(creation_date__gte=from_date)
if to_date:
queryset = queryset.filter(creation_date__lt=to_date + datetime.timedelta(days=1))
if not queryset.exists():
message = _('No matching %s found for the given criteria. '
'Please try again.') % self.opts.verbose_name_plural
self.message_user(request, message, level=messages.WARNING)
if request.is_ajax():
data = {
'reloadBrowser': True,
'submissionCount': 0,
}
return JsonResponse(data)
return redirect('admin:%s_%s_export' % info)
latest_submission = queryset[:1].get()
dataset = Dataset(title=latest_submission.plugin.name)
if not headers:
headers = [field['label'].strip() for field in latest_submission.form_data]
for submission in queryset:
for field in submission.form_data:
label = field['label'].strip()
if label not in headers:
headers.append(label)
if request.is_ajax():
data = {
'reloadBrowser': False,
'submissionCount': queryset.count(),
'availableHeaders': headers,
}
return JsonResponse(data)
headers.extend(['Submitted on', 'Sender IP', 'Referrer URL'])
dataset.headers = headers
def humanize(field):
value = field['value']
field_type = field['type']
if value in (None, '', [], (), {}):
return None
if field_type == 'checkbox':
value = yesno(bool(value), u'{0},{1}'.format(_('Yes'), _('No')))
if field_type == 'checkbox_multiple':
value = ', '.join(list(value))
return value
for submission in queryset:
row = [None] * len(headers)
for field in submission.form_data:
label = field['label'].strip()
if label in headers:
row[headers.index(label)] = humanize(field)
row[-3] = submission.creation_date.strftime(
settings.DJANGOCMS_FORMS_DATETIME_FORMAT)
row[-2] = submission.ip
row[-1] = submission.referrer
dataset.append(row)
mimetype = {
'xls': 'application/vnd.ms-excel',
'csv': 'text/csv',
'html': 'text/html',
'yaml': 'text/yaml',
'json': 'application/json',
}
file_type = data.get('file_type', 'xls')
filename = settings.DJANGOCMS_FORMS_EXPORT_FILENAME.format(
form_name=slugify(latest_submission.plugin.name))
filename = timezone.now().strftime(filename)
filename = '%s.%s' % (filename, file_type)
response = HttpResponse(
getattr(dataset, file_type), {
'content_type': mimetype.get(file_type, 'application/octet-stream')
})
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
# Wrap in all admin layout
fieldsets = ((None, {'fields': form.fields.keys()}),)
adminform = AdminForm(form, fieldsets, {}, model_admin=self)
media = self.media + adminform.media
context = {
'title': _('Export %s') % force_text(self.opts.verbose_name_plural),
'adminform': adminform,
'is_popup': '_popup' in request.REQUEST,
'media': mark_safe(media),
'errors': AdminErrorList(form, ()),
'app_label': self.opts.app_label,
}
return self.render_export_form(request, context, form_url)
def render_export_form(self, request, context, form_url=''):
"""
Render the from submission export form.
"""
context.update({
'has_change_permission': self.has_change_permission(request),
'form_url': mark_safe(form_url),
'opts': self.opts,
'add': True,
'save_on_top': self.save_on_top,
})
return TemplateResponse(request, self.export_form_template, context)
admin.site.register(FormSubmission, FormSubmissionAdmin)