Added ExportViewMixin (#692)
* Created ExportViewMixin * Added ExportViewMixin tests Added VIM files to .gitignore Django<1.9 fix Django 2.0 Fix Splitted View behaviors Added ExportMixinView
This commit is contained in:
parent
65416fbcef
commit
edc18e7653
|
@ -11,3 +11,4 @@ dist/
|
|||
.idea/
|
||||
*.python-version
|
||||
.coverage
|
||||
*.sw[po]
|
||||
|
|
1
AUTHORS
1
AUTHORS
|
@ -104,3 +104,4 @@ The following is a list of much appreciated contributors:
|
|||
* pacotole (Pacotole)
|
||||
* KenyaDonDraper
|
||||
* andrew-bro (Andrei Loskutov)
|
||||
* ZuluPro (Anthony Monthe)
|
||||
|
|
|
@ -31,7 +31,7 @@ from .forms import (
|
|||
from .resources import (
|
||||
modelresource_factory,
|
||||
)
|
||||
from .formats import base_formats
|
||||
from .formats.base_formats import DEFAULT_FORMATS
|
||||
from .results import RowResult
|
||||
from .tmp_storages import TempFolderStorage
|
||||
from .signals import post_export, post_import
|
||||
|
@ -55,19 +55,6 @@ if isinstance(TMP_STORAGE_CLASS, six.string_types):
|
|||
msg = "Could not import '%s' for import_export setting 'IMPORT_EXPORT_TMP_STORAGE_CLASS'" % TMP_STORAGE_CLASS
|
||||
raise ImportError(msg)
|
||||
|
||||
#: These are the default formats for import and export. Whether they can be
|
||||
#: used or not is depending on their implementation in the tablib library.
|
||||
DEFAULT_FORMATS = (
|
||||
base_formats.CSV,
|
||||
base_formats.XLS,
|
||||
base_formats.XLSX,
|
||||
base_formats.TSV,
|
||||
base_formats.ODS,
|
||||
base_formats.JSON,
|
||||
base_formats.YAML,
|
||||
base_formats.HTML,
|
||||
)
|
||||
|
||||
|
||||
class ImportExportMixinBase(object):
|
||||
def get_model_info(self):
|
||||
|
|
|
@ -223,3 +223,16 @@ class XLSX(TablibFormat):
|
|||
row_values = [cell.value for cell in row]
|
||||
dataset.append(row_values)
|
||||
return dataset
|
||||
|
||||
#: These are the default formats for import and export. Whether they can be
|
||||
#: used or not is depending on their implementation in the tablib library.
|
||||
DEFAULT_FORMATS = (
|
||||
CSV,
|
||||
XLS,
|
||||
XLSX,
|
||||
TSV,
|
||||
ODS,
|
||||
JSON,
|
||||
YAML,
|
||||
HTML,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
from django.http import HttpResponse
|
||||
from django.views.generic.edit import FormView
|
||||
from django.utils.timezone import now
|
||||
|
||||
from .formats import base_formats
|
||||
from .resources import modelresource_factory
|
||||
from .signals import post_export
|
||||
from .forms import ExportForm
|
||||
|
||||
|
||||
class ExportViewMixin(object):
|
||||
formats = base_formats.DEFAULT_FORMATS
|
||||
form_class = ExportForm
|
||||
resource_class = None
|
||||
|
||||
def get_export_formats(self):
|
||||
"""
|
||||
Returns available export formats.
|
||||
"""
|
||||
return [f for f in self.formats if f().can_export()]
|
||||
|
||||
def get_resource_class(self):
|
||||
if not self.resource_class:
|
||||
return modelresource_factory(self.model)
|
||||
return self.resource_class
|
||||
|
||||
def get_export_resource_class(self):
|
||||
"""
|
||||
Returns ResourceClass to use for export.
|
||||
"""
|
||||
return self.get_resource_class()
|
||||
|
||||
def get_resource_kwargs(self, request, *args, **kwargs):
|
||||
return {}
|
||||
|
||||
def get_export_resource_kwargs(self, request, *args, **kwargs):
|
||||
return self.get_resource_kwargs(request, *args, **kwargs)
|
||||
|
||||
def get_export_data(self, file_format, queryset, *args, **kwargs):
|
||||
"""
|
||||
Returns file_format representation for given queryset.
|
||||
"""
|
||||
resource_class = self.get_export_resource_class()
|
||||
data = resource_class(**self.get_export_resource_kwargs(self.request))\
|
||||
.export(queryset, *args, **kwargs)
|
||||
export_data = file_format.export_data(data)
|
||||
return export_data
|
||||
|
||||
def get_export_filename(self, file_format):
|
||||
date_str = now().strftime('%Y-%m-%d')
|
||||
filename = "%s-%s.%s" % (self.model.__name__,
|
||||
date_str,
|
||||
file_format.get_extension())
|
||||
return filename
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ExportViewMixin, self).get_context_data(**kwargs)
|
||||
return context
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(ExportViewMixin, self).get_form_kwargs()
|
||||
kwargs['formats'] = self.get_export_formats()
|
||||
return kwargs
|
||||
|
||||
|
||||
class ExportViewFormMixin(ExportViewMixin, FormView):
|
||||
def form_valid(self, form):
|
||||
formats = self.get_export_formats()
|
||||
file_format = formats[
|
||||
int(form.cleaned_data['file_format'])
|
||||
]()
|
||||
if hasattr(self, 'get_filterset'):
|
||||
queryset = self.get_filterset(self.get_filterset_class()).qs
|
||||
else:
|
||||
queryset = self.get_queryset()
|
||||
export_data = self.get_export_data(file_format, queryset)
|
||||
content_type = file_format.get_content_type()
|
||||
# Django 1.7 uses the content_type kwarg instead of mimetype
|
||||
try:
|
||||
response = HttpResponse(export_data, content_type=content_type)
|
||||
except TypeError:
|
||||
response = HttpResponse(export_data, mimetype=content_type)
|
||||
response['Content-Disposition'] = 'attachment; filename=%s' % (
|
||||
self.get_export_filename(file_format),
|
||||
)
|
||||
|
||||
post_export.send(sender=None, model=self.model)
|
||||
return response
|
|
@ -0,0 +1,5 @@
|
|||
{{ form }}
|
||||
|
||||
{% for obj in object_list %}
|
||||
{{ obj }}
|
||||
{% endfor %}
|
|
@ -0,0 +1,29 @@
|
|||
from __future__ import unicode_literals
|
||||
from django.test.testcases import TestCase
|
||||
try:
|
||||
from django.urls import reverse
|
||||
except ImportError:
|
||||
from django.core.urlresolvers import reverse
|
||||
from core.models import Category
|
||||
|
||||
|
||||
class ExportViewMixinTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.url = reverse('export-category')
|
||||
self.cat1 = Category.objects.create(name='Cat 1')
|
||||
self.cat2 = Category.objects.create(name='Cat 2')
|
||||
|
||||
def test_get(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertContains(response, self.cat1.name, status_code=200)
|
||||
self.assertTrue(response['Content-Type'], 'text/html')
|
||||
|
||||
def test_post(self):
|
||||
data = {
|
||||
'file_format': '0',
|
||||
}
|
||||
response = self.client.post(self.url, data)
|
||||
self.assertContains(response, self.cat1.name, status_code=200)
|
||||
self.assertTrue(response.has_header("Content-Disposition"))
|
||||
self.assertTrue(response['Content-Type'], 'text/csv')
|
|
@ -7,3 +7,4 @@ from .instance_loaders_tests import *
|
|||
from .admin_integration_tests import *
|
||||
from .base_formats_tests import *
|
||||
from .tmp_storages_tests import *
|
||||
from .mixins import *
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
from django.views.generic.list import ListView
|
||||
from import_export import mixins
|
||||
from . import models
|
||||
|
||||
|
||||
class CategoryExportView(mixins.ExportViewFormMixin, ListView):
|
||||
model = models.Category
|
|
@ -3,13 +3,16 @@ from __future__ import unicode_literals
|
|||
from django.conf.urls import url, include
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
|
||||
|
||||
from django.contrib import admin
|
||||
admin.autodiscover()
|
||||
|
||||
from core import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^export/category/', views.CategoryExportView.as_view(),
|
||||
name='export-category'),
|
||||
]
|
||||
|
||||
urlpatterns += staticfiles_urlpatterns()
|
||||
|
|
Loading…
Reference in New Issue