local changes from server
[redakcja.git] / apps / forms_builder / forms / admin.py
diff --git a/apps/forms_builder/forms/admin.py b/apps/forms_builder/forms/admin.py
new file mode 100644 (file)
index 0000000..61a6d0b
--- /dev/null
@@ -0,0 +1,203 @@
+from __future__ import unicode_literals
+from future.builtins import bytes, open
+
+from csv import writer
+from mimetypes import guess_type
+from os.path import join
+from datetime import datetime
+from io import BytesIO, StringIO
+
+from django.conf.urls import patterns, url
+from django.contrib import admin
+from django.core.files.storage import FileSystemStorage
+from django.core.urlresolvers import reverse
+from django.db.models import Count
+from django.http import HttpResponse, HttpResponseRedirect
+from django.shortcuts import render_to_response, get_object_or_404
+from django.template import RequestContext
+from django.utils.translation import ungettext, ugettext_lazy as _
+
+from forms_builder.forms.forms import EntriesForm
+from forms_builder.forms.models import Form, Field, FormEntry, FieldEntry
+from forms_builder.forms.settings import CSV_DELIMITER, UPLOAD_ROOT
+from forms_builder.forms.settings import USE_SITES, EDITABLE_SLUGS
+from forms_builder.forms.utils import now, slugify
+
+try:
+    import xlwt
+    XLWT_INSTALLED = True
+    XLWT_DATETIME_STYLE = xlwt.easyxf(num_format_str='MM/DD/YYYY HH:MM:SS')
+except ImportError:
+    XLWT_INSTALLED = False
+
+
+fs = FileSystemStorage(location=UPLOAD_ROOT)
+form_admin_filter_horizontal = ()
+form_admin_fieldsets = [
+    (None, {"fields": ("title", ("status", "login_required",),
+        ("publish_date", "expiry_date",),
+        "intro", "button_text", "response", "redirect_url")}),
+    (_("Email"), {"fields": ("send_email", "email_from", "email_copies",
+        "email_subject", "email_message")}),]
+
+if EDITABLE_SLUGS:
+    form_admin_fieldsets.append(
+            (_("Slug"), {"fields": ("slug",), "classes": ("collapse",)}))
+
+if USE_SITES:
+    form_admin_fieldsets.append((_("Sites"), {"fields": ("sites",),
+        "classes": ("collapse",)}))
+    form_admin_filter_horizontal = ("sites",)
+
+
+class FieldAdmin(admin.TabularInline):
+    model = Field
+    exclude = ('slug', )
+
+
+class FormAdmin(admin.ModelAdmin):
+    formentry_model = FormEntry
+    fieldentry_model = FieldEntry
+
+    inlines = (FieldAdmin,)
+    list_display = ("title", "status", "email_copies", "publish_date",
+                    "expiry_date", "total_entries", "admin_links")
+    list_display_links = ("title",)
+    list_editable = ("status", "email_copies", "publish_date", "expiry_date")
+    list_filter = ("status",)
+    filter_horizontal = form_admin_filter_horizontal
+    search_fields = ("title", "intro", "response", "email_from",
+                     "email_copies")
+    radio_fields = {"status": admin.HORIZONTAL}
+    fieldsets = form_admin_fieldsets
+
+    def get_queryset(self, request):
+        """
+        Annotate the queryset with the entries count for use in the
+        admin list view.
+        """
+        qs = super(FormAdmin, self).get_queryset(request)
+        return qs.annotate(total_entries=Count("entries"))
+
+    def get_urls(self):
+        """
+        Add the entries view to urls.
+        """
+        urls = super(FormAdmin, self).get_urls()
+        extra_urls = patterns("",
+            url("^(?P<form_id>\d+)/entries/$",
+                self.admin_site.admin_view(self.entries_view),
+                name="form_entries"),
+            url("^(?P<form_id>\d+)/entries/show/$",
+                self.admin_site.admin_view(self.entries_view),
+                {"show": True}, name="form_entries_show"),
+            url("^(?P<form_id>\d+)/entries/export/$",
+                self.admin_site.admin_view(self.entries_view),
+                {"export": True}, name="form_entries_export"),
+            url("^file/(?P<field_entry_id>\d+)/$",
+                self.admin_site.admin_view(self.file_view),
+                name="form_file"),
+        )
+        return extra_urls + urls
+
+    def entries_view(self, request, form_id, show=False, export=False,
+                     export_xls=False):
+        """
+        Displays the form entries in a HTML table with option to
+        export as CSV file.
+        """
+        if request.POST.get("back"):
+            bits = (self.model._meta.app_label, self.model.__name__.lower())
+            change_url = reverse("admin:%s_%s_change" % bits, args=(form_id,))
+            return HttpResponseRedirect(change_url)
+        form = get_object_or_404(self.model, id=form_id)
+        post = request.POST or None
+        args = form, request, self.formentry_model, self.fieldentry_model, post
+        entries_form = EntriesForm(*args)
+        delete = "%s.delete_formentry" % self.formentry_model._meta.app_label
+        can_delete_entries = request.user.has_perm(delete)
+        submitted = entries_form.is_valid() or show or export or export_xls
+        export = export or request.POST.get("export")
+        export_xls = export_xls or request.POST.get("export_xls")
+        if submitted:
+            if export:
+                response = HttpResponse(content_type="text/csv")
+                fname = "%s-%s.csv" % (form.slug, slugify(now().ctime()))
+                attachment = "attachment; filename=%s" % fname
+                response["Content-Disposition"] = attachment
+                queue = StringIO()
+                try:
+                    csv = writer(queue, delimiter=CSV_DELIMITER)
+                    writerow = csv.writerow
+                except TypeError:
+                    queue = BytesIO()
+                    delimiter = bytes(CSV_DELIMITER, encoding="utf-8")
+                    csv = writer(queue, delimiter=delimiter)
+                    writerow = lambda row: csv.writerow([c.encode("utf-8")
+                        if hasattr(c, "encode") else c for c in row])
+                writerow(entries_form.columns())
+                for row in entries_form.rows(csv=True):
+                    writerow(row)
+                data = queue.getvalue()
+                response.write(data)
+                return response
+            elif XLWT_INSTALLED and export_xls:
+                response = HttpResponse(content_type="application/vnd.ms-excel")
+                fname = "%s-%s.xls" % (form.slug, slugify(now().ctime()))
+                attachment = "attachment; filename=%s" % fname
+                response["Content-Disposition"] = attachment
+                queue = BytesIO()
+                workbook = xlwt.Workbook(encoding='utf8')
+                sheet = workbook.add_sheet(form.title[:31])
+                for c, col in enumerate(entries_form.columns()):
+                    sheet.write(0, c, col)
+                for r, row in enumerate(entries_form.rows(csv=True)):
+                    for c, item in enumerate(row):
+                        if isinstance(item, datetime):
+                            item = item.replace(tzinfo=None)
+                            sheet.write(r + 2, c, item, XLWT_DATETIME_STYLE)
+                        else:
+                            sheet.write(r + 2, c, item)
+                workbook.save(queue)
+                data = queue.getvalue()
+                response.write(data)
+                return response
+            elif request.POST.get("delete") and can_delete_entries:
+                selected = request.POST.getlist("selected")
+                if selected:
+                    try:
+                        from django.contrib.messages import info
+                    except ImportError:
+                        def info(request, message, fail_silently=True):
+                            request.user.message_set.create(message=message)
+                    entries = self.formentry_model.objects.filter(id__in=selected)
+                    count = entries.count()
+                    if count > 0:
+                        entries.delete()
+                        message = ungettext("1 entry deleted",
+                                            "%(count)s entries deleted", count)
+                        info(request, message % {"count": count})
+        template = "admin/forms/entries.html"
+        context = {"title": _("View Entries"), "entries_form": entries_form,
+                   "opts": self.model._meta, "original": form,
+                   "can_delete_entries": can_delete_entries,
+                   "submitted": submitted,
+                   "xlwt_installed": XLWT_INSTALLED}
+        return render_to_response(template, context, RequestContext(request))
+
+    def file_view(self, request, field_entry_id):
+        """
+        Output the file for the requested field entry.
+        """
+        model = self.fieldentry_model
+        field_entry = get_object_or_404(model, id=field_entry_id)
+        path = join(fs.location, field_entry.value)
+        response = HttpResponse(content_type=guess_type(path)[0])
+        f = open(path, "r+b")
+        response["Content-Disposition"] = "attachment; filename=%s" % f.name
+        response.write(f.read())
+        f.close()
+        return response
+
+
+admin.site.register(Form, FormAdmin)