Skip to content

Commit

Permalink
fix crash on export with custom column name (#1829)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewhegarty committed May 13, 2024
1 parent 0e0071a commit 31524a4
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 8 deletions.
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Changelog
- remove unreachable code (`1825 <https://github.com/django-import-export/django-import-export/pull/1825>`_)
- fix issue with widget assignment for custom ``ForeignKey`` subclasses (`1826 <https://github.com/django-import-export/django-import-export/pull/1826>`_)
- performance: select of valid pks for export restricted to action exports (`1827 <https://github.com/django-import-export/django-import-export/pull/1827>`_)
- fix crash on export with custom column name (`1828 <https://github.com/django-import-export/django-import-export/pull/1828>`_)

4.0.1 (2024-05-08)
------------------
Expand Down
22 changes: 18 additions & 4 deletions import_export/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,8 +1048,18 @@ def export_field(self, field, instance):
return field.export(instance)

def get_export_fields(self):
export_order = self.get_export_order()
return [self.fields[f] for f in export_order]
export_fields = []
for field_name in self.get_export_order():
if field_name in self.fields:
export_fields.append(self.fields[field_name])
continue
# issue 1828
# allow for fields to be referenced by column_name in `fields` list
for field in self.fields.values():
if field.column_name == field_name:
export_fields.append(field)
continue
return export_fields

def export_resource(self, instance, fields=None):
export_fields = self.get_export_fields()
Expand All @@ -1058,15 +1068,19 @@ def export_resource(self, instance, fields=None):
return [
self.export_field(field, instance)
for field in export_fields
if field.attribute in fields
if field.attribute in fields or field.column_name in fields
]

return [self.export_field(field, instance) for field in export_fields]

def get_export_headers(self, fields=None):
export_fields = self.get_export_fields()
if isinstance(fields, list) and fields:
return [f.column_name for f in export_fields if f.attribute in fields]
return [
f.column_name
for f in export_fields
if f.attribute in fields or f.column_name in fields
]

return [force_str(field.column_name) for field in export_fields]

Expand Down
2 changes: 1 addition & 1 deletion tests/core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Meta:
fields = ("id", "author_email", "name", "published")


class CustomBookAdmin(ImportExportModelAdmin):
class CustomBookAdmin(ExportActionModelAdmin, ImportExportModelAdmin):
"""Example usage of custom import / export forms"""

resource_classes = [EBookResource]
Expand Down
45 changes: 43 additions & 2 deletions tests/core/tests/admin_integration/test_export.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from datetime import datetime
from datetime import date, datetime
from io import BytesIO
from unittest import mock
from unittest.mock import MagicMock, patch

import chardet
import tablib
from core.admin import BookAdmin, BookResource
from core.admin import BookAdmin, BookResource, EBookResource
from core.models import Author, Book, UUIDCategory
from core.tests.admin_integration.mixins import AdminTestMixin
from core.tests.utils import ignore_utcnow_deprecation_warning
Expand Down Expand Up @@ -465,3 +465,44 @@ def test_selectable_fields_rendered_with_resource_index_attribute(self) -> None:
response_content.count(f'resource-index="{index}"'),
len(resource_fields),
)


class CustomColumnNameExportTest(AdminTestMixin, TestCase):
"""Test export ok when column name is defined in fields list (issue 1828)."""

def setUp(self):
super().setUp()
EBookResource._meta.fields = ("id", "author_email", "name", "published_date")

def tearDown(self):
super().tearDown()
EBookResource._meta.fields = ("id", "author_email", "name", "published")

def test_export_with_custom_field(self):
a = Author.objects.create(id=11, name="Ian Fleming")
book = Book.objects.create(
name="Moonraker", author=a, published=date(1955, 4, 5)
)
data = {
"format": "0",
"author": a.id,
"resource": "",
"ebookresource_id": True,
"ebookresource_author_email": True,
"ebookresource_name": True,
"ebookresource_published_date": True,
}
date_str = datetime.now().strftime("%Y-%m-%d")
response = self.client.post(self.ebook_export_url, data)
self.assertEqual(response.status_code, 200)
self.assertTrue(response.has_header("Content-Disposition"))
self.assertEqual(response["Content-Type"], "text/csv")
self.assertEqual(
response["Content-Disposition"],
'attachment; filename="EBook-{}.csv"'.format(date_str),
)
s = (
"id,author_email,name,published_date\r\n"
f"{book.id},,Moonraker,1955-04-05\r\n"
)
self.assertEqual(str.encode(s), response.content)
2 changes: 1 addition & 1 deletion tests/core/tests/admin_integration/test_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ def test_import_preview_order(self):


class CustomColumnNameImportTest(AdminTestMixin, TestCase):
"""Test preview order displayed correctly (issue 1815)."""
"""Handle custom column name import (issue 1822)."""

fixtures = ["author"]

Expand Down

0 comments on commit 31524a4

Please sign in to comment.