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:
Anthony Monthe 2018-05-31 17:56:56 +01:00 committed by Bojan Mihelac
parent 65416fbcef
commit edc18e7653
10 changed files with 150 additions and 15 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ dist/
.idea/
*.python-version
.coverage
*.sw[po]

View File

@ -104,3 +104,4 @@ The following is a list of much appreciated contributors:
* pacotole (Pacotole)
* KenyaDonDraper
* andrew-bro (Andrei Loskutov)
* ZuluPro (Anthony Monthe)

View File

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

View File

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

88
import_export/mixins.py Normal file
View File

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

View File

@ -0,0 +1,5 @@
{{ form }}
{% for obj in object_list %}
{{ obj }}
{% endfor %}

View File

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

View File

@ -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 *

7
tests/core/views.py Normal file
View File

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

View File

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