Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed to work with newest version of Django. Fixes for viewing and downloading large reports. #54

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions django_qbe/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from django import forms
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from ordered_model.admin import OrderedModelAdmin

from .models import SavedReport


class SavedReportForm(forms.ModelForm):
model = SavedReport


class SavedReportAdmin(ImportExportModelAdmin, OrderedModelAdmin):
form = SavedReportForm
fields = [str(f).split('.')[-1] for f in SavedReport._meta.get_fields() if f.name not in ['id', 'order']]
list_display = ['title', 'description', 'report_type', 'move_up_down_links', 'created', 'modified']
readonly_fields = ['created', 'modified']
list_filter = ['report_type']

def save_form(self, request, form, change):
return super(SavedReportAdmin, self).save_form(request, form, change)


admin.site.register(SavedReport, SavedReportAdmin)
69 changes: 38 additions & 31 deletions django_qbe/exports.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
from future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
# -*- coding: utf-8 -*-
import codecs
import csv
from builtins import str

import collections
from collections import OrderedDict as SortedDict
from django.http import StreamingHttpResponse
from future import standard_library
from io import StringIO

from django.http import HttpResponse
from django.utils.datastructures import SortedDict
standard_library.install_aliases()

__all__ = ("formats", )
__all__ = ("formats",)


class FormatsException(Exception):
pass


class Formats(SortedDict):

def add(self, format):
parent = self

def decorator(func):
if callable(func):
if isinstance(func, collections.Callable):
parent.update({format: func})
else:
raise FormatsException("func is not a function.")
Expand All @@ -35,62 +34,70 @@ def decorator(func):


# Taken from http://docs.python.org/library/csv.html#csv-examples
class UnicodeWriter(object):
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_tab, encoding="utf-8", **kwds):
def __init__(self, dialect=csv.excel_tab, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()

def writerow(self, row):
self.writer.writerow([str(s).encode("utf-8") for s in row])
self.writer.writerow([str(s) for s in row])

def get_values(self):
# 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)
ret = self.queue.getvalue()
# empty queue
self.queue.truncate(0)
return ret.encode('utf-8').lstrip(b'\0')

def writerows(self, rows):
for row in rows:
self.writerow(row)


def base_export(labels, results, dialect=csv.excel_tab):
output = StringIO()
w = UnicodeWriter(output, dialect=dialect)
w = UnicodeWriter(dialect=dialect)
count = 0
w.writerow(labels)
for row in results:
count += 1
w.writerow(row)
output.seek(0)
return output.read()

if count % 1000 == 0:
yield w.get_values()

yield w.get_values()


def make_attachment(response, ext):
response['Content-Disposition'] = 'attachment; filename=export.%s' % ext
return response


@formats.add("csv")
def csv_format(labels, results):
output = base_export(labels, results, dialect=csv.excel)
content_type = "text/csv"
return HttpResponse(output, content_type=content_type)
return make_attachment(
StreamingHttpResponse(base_export(labels, results, dialect=csv.excel), content_type=content_type), "csv"
)


@formats.add("ods")
def ods_format(labels, results):
output = base_export(labels, results)
content_type = "application/vnd.oasis.opendocument.spreadsheet"
return HttpResponse(output, content_type=content_type)
return make_attachment(
StreamingHttpResponse(base_export(labels, results, dialect=csv.excel), content_type=content_type), "ods"
)


@formats.add("xls")
def xls_format(labels, results):
output = base_export(labels, results)
content_type = "application/vnd.ms-excel"
return HttpResponse(output, content_type=content_type)
return make_attachment(
StreamingHttpResponse(base_export(labels, results, dialect=csv.excel), content_type=content_type), "xls"
)
Loading