Skip to content

Commit

Permalink
Replace the CSV export with an XLSX export
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiask committed Feb 1, 2019
1 parent ee53b6b commit 25c4d0a
Show file tree
Hide file tree
Showing 6 changed files with 13 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ matrix:
- env: REQ="https://github.com/django/django/archive/master.zip#egg=Django"
install:
- pip install -U pip wheel
- pip install $REQ FeinCMS django-admin-ordering django-mptt Pillow
- pip install $REQ Pillow FeinCMS django-admin-ordering django-mptt xlsxdocument
- python setup.py install
script: cd tests && ./manage.py test -v2 testapp
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Change log
<https://black.readthedocs.io/>`__
* Made `django-admin-ordering
<https://github.com/matthiask/django-admin-ordering/>`__ a dependency.
* Replaced the CSV export with an XLSX export based on `xlsxdocument
<https://github.com/matthiask/xlsxdocument>`__. It just is a better
format.


0.12
Expand Down
18 changes: 1 addition & 17 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Every field can optionally be declared mandatory, default values and help texts
are available too. That's it.

By default, form data is sent by e-mail to a freely definable e-mail address
and stored in the database (a CSV export of saved submissions is provided too).
and stored in the database (a XLSX export of saved submissions is provided too).
It is possible to add your own actions as well.


Expand Down Expand Up @@ -115,22 +115,6 @@ additional arguments added in the future:
char field, and accesses its value using ``config['email']``.


Configuring the export
======================

The CSV export of form submissions uses the Python's CSV module, the Excel
dialect and UTF-8 encoding by default. If your main target is Excel, you should
probably add the following setting to work around Excel's abysmal handling of
CSV files encoded in anything but latin-1::

FORM_DESIGNER_EXPORT = {
'encoding': 'latin-1',
}

You may add additional keyword arguments here which will be used during the
instantiation of ``csv.writer``.


ReCaptcha
=========

Expand Down
53 changes: 6 additions & 47 deletions form_designer/admin.py
Original file line number Diff line number Diff line change
@@ -1,57 +1,19 @@
from __future__ import unicode_literals

import codecs
import csv
import json
from io import BytesIO

from django import forms
from django.conf import settings
from django.conf.urls import url
from django.contrib import admin
from django.db.models import Model
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.utils import six
from django.utils.encoding import smart_text
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _

from admin_ordering.admin import OrderableAdmin
from form_designer import models

if six.PY3:
UnicodeWriter = csv.writer
else:

class UnicodeWriter:
"""
A CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
"""

def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = BytesIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)("replace")

def writerow(self, row):
row = [smart_text(s) for s in row]
self.writer.writerow([s.encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)

def writerows(self, rows):
for row in rows:
self.writerow(row)
from xlsxdocument import XLSXDocument


def jsonize(v):
Expand Down Expand Up @@ -187,13 +149,10 @@ def export_submissions(self, request, form_id):
# (fairly gracefully handles changes in form fields between
# submissions)

response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = "attachment; filename=form_submissions.csv"
writer = UnicodeWriter(
response, **getattr(settings, "FORM_DESIGNER_EXPORT", {})
)
writer.writerows(rows)
return response
xlsx = XLSXDocument()
xlsx.add_sheet(slugify(form.title))
xlsx.table([], rows)
return xlsx.to_response("%s.xlsx" % slugify(form.title))

def get_urls(self):
return [
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def read(filename):
platforms=["OS Independent"],
packages=find_packages(exclude=[]),
include_package_data=True,
install_requires=["django-admin-ordering"],
install_requires=["django-admin-ordering", "xlsxdocument"],
classifiers=[
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ deps =
FeinCMS
django-admin-ordering
django-mptt
xlsxdocument
coverage
changedir = {toxinidir}
skip_install = true
Expand Down

0 comments on commit 25c4d0a

Please sign in to comment.