Skip to content

Commit 63c0ac7

Browse files
authored
Merge pull request #100 from CorneiZeR/resolve_conflicts
Enhance nested serializer handling by skipping write_only fields.
2 parents fe9047c + 6220500 commit 63c0ac7

File tree

6 files changed

+50
-7
lines changed

6 files changed

+50
-7
lines changed

drf_excel/renderers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ def _flatten_serializer_keys(
260260
use_labels=False,
261261
):
262262
"""
263-
Iterate through serializer fields recursively when field is a nested serializer.
263+
Iterate through serializer fields recursively when field is a nested serializer. Skip write_only fields.
264264
"""
265265

266266
def _get_label(parent_label, label_sep, obj):
@@ -278,7 +278,7 @@ def _get_label(parent_label, label_sep, obj):
278278
for k, v in _fields.items():
279279
new_key = f"{parent_key}{key_sep}{k}" if parent_key else k
280280
# Skip headers we want to ignore
281-
if new_key in self.ignore_headers:
281+
if new_key in self.ignore_headers or getattr(v, "write_only", False):
282282
continue
283283
# Iterate through fields if field is a serializer. Check for labels and
284284
# append if `use_labels` is True. Fallback to using keys.

tests/test_viewset_mixin.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from rest_framework.test import APIClient
55
from time_machine import TimeMachineFixture
66

7-
from tests.testapp.models import AllFieldsModel, ExampleModel, Tag
7+
from tests.testapp.models import AllFieldsModel, ExampleModel, SecretFieldModel, Tag
88

99
pytestmark = pytest.mark.django_db
1010

@@ -93,3 +93,20 @@ def test_all_fields_viewset(
9393
True,
9494
"test, example",
9595
]
96+
97+
98+
def test_secret_field_viewset(api_client, workbook_reader):
99+
SecretFieldModel.objects.create(title="foo", secret="bar")
100+
101+
response = api_client.get("/secret-field/")
102+
assert response.status_code == 200
103+
104+
wb = workbook_reader(response.content)
105+
sheet = wb.worksheets[0]
106+
rows = list(sheet.rows)
107+
assert len(rows) == 2
108+
header, data = rows
109+
110+
# Check that the secret field is not included in the header or data
111+
assert [col.value for col in header] == ["title"]
112+
assert [col.value for col in data] == ["foo"]

tests/testapp/models.py

+8
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,11 @@ def __str__(self):
3030

3131
def get_tag_names(self):
3232
return [tag.name for tag in self.tags.all()]
33+
34+
35+
class SecretFieldModel(models.Model):
36+
title = models.CharField(max_length=100)
37+
secret = models.CharField(max_length=100)
38+
39+
def __str__(self):
40+
return self.title

tests/testapp/serializers.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from rest_framework import serializers
22

3-
from .models import AllFieldsModel, ExampleModel
3+
from .models import AllFieldsModel, ExampleModel, SecretFieldModel
44

55

66
class ExampleSerializer(serializers.ModelSerializer):
@@ -23,3 +23,13 @@ class Meta:
2323
"is_active",
2424
"tags",
2525
)
26+
27+
28+
class SecretFieldSerializer(serializers.ModelSerializer):
29+
secret_external = serializers.CharField(write_only=True)
30+
31+
class Meta:
32+
model = SecretFieldModel
33+
fields = ("title", "secret", "secret_external")
34+
35+
extra_kwargs = {"secret": {"write_only": True}}

tests/testapp/views.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from drf_excel.mixins import XLSXFileMixin
44
from drf_excel.renderers import XLSXRenderer
55

6-
from .models import AllFieldsModel, ExampleModel
7-
from .serializers import AllFieldsSerializer, ExampleSerializer
6+
from .models import AllFieldsModel, ExampleModel, SecretFieldModel
7+
from .serializers import AllFieldsSerializer, ExampleSerializer, SecretFieldSerializer
88

99

1010
class ExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
@@ -19,3 +19,10 @@ class AllFieldsViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
1919
serializer_class = AllFieldsSerializer
2020
renderer_classes = (XLSXRenderer,)
2121
filename = "al_fileds.xlsx"
22+
23+
24+
class SecretFieldViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
25+
queryset = SecretFieldModel.objects.all()
26+
serializer_class = SecretFieldSerializer
27+
renderer_classes = (XLSXRenderer,)
28+
filename = "secret.xlsx"

tests/urls.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from rest_framework import routers
22

3-
from .testapp.views import AllFieldsViewSet, ExampleViewSet
3+
from .testapp.views import AllFieldsViewSet, ExampleViewSet, SecretFieldViewSet
44

55
router = routers.SimpleRouter()
66
router.register(r"examples", ExampleViewSet)
77
router.register(r"all-fields", AllFieldsViewSet)
8+
router.register(r"secret-field", SecretFieldViewSet)
89

910
urlpatterns = router.urls

0 commit comments

Comments
 (0)