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
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)
|
|
|