Skip to content

Commit

Permalink
Merge pull request #100 from CorneiZeR/resolve_conflicts
Browse files Browse the repository at this point in the history
Enhance nested serializer handling by skipping write_only fields.
  • Loading branch information
FlipperPA authored Oct 18, 2024
2 parents fe9047c + 6220500 commit 63c0ac7
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 7 deletions.
4 changes: 2 additions & 2 deletions drf_excel/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def _flatten_serializer_keys(
use_labels=False,
):
"""
Iterate through serializer fields recursively when field is a nested serializer.
Iterate through serializer fields recursively when field is a nested serializer. Skip write_only fields.
"""

def _get_label(parent_label, label_sep, obj):
Expand All @@ -278,7 +278,7 @@ def _get_label(parent_label, label_sep, obj):
for k, v in _fields.items():
new_key = f"{parent_key}{key_sep}{k}" if parent_key else k
# Skip headers we want to ignore
if new_key in self.ignore_headers:
if new_key in self.ignore_headers or getattr(v, "write_only", False):
continue
# Iterate through fields if field is a serializer. Check for labels and
# append if `use_labels` is True. Fallback to using keys.
Expand Down
19 changes: 18 additions & 1 deletion tests/test_viewset_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from rest_framework.test import APIClient
from time_machine import TimeMachineFixture

from tests.testapp.models import AllFieldsModel, ExampleModel, Tag
from tests.testapp.models import AllFieldsModel, ExampleModel, SecretFieldModel, Tag

pytestmark = pytest.mark.django_db

Expand Down Expand Up @@ -93,3 +93,20 @@ def test_all_fields_viewset(
True,
"test, example",
]


def test_secret_field_viewset(api_client, workbook_reader):
SecretFieldModel.objects.create(title="foo", secret="bar")

response = api_client.get("/secret-field/")
assert response.status_code == 200

wb = workbook_reader(response.content)
sheet = wb.worksheets[0]
rows = list(sheet.rows)
assert len(rows) == 2
header, data = rows

# Check that the secret field is not included in the header or data
assert [col.value for col in header] == ["title"]
assert [col.value for col in data] == ["foo"]
8 changes: 8 additions & 0 deletions tests/testapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ def __str__(self):

def get_tag_names(self):
return [tag.name for tag in self.tags.all()]


class SecretFieldModel(models.Model):
title = models.CharField(max_length=100)
secret = models.CharField(max_length=100)

def __str__(self):
return self.title
12 changes: 11 additions & 1 deletion tests/testapp/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework import serializers

from .models import AllFieldsModel, ExampleModel
from .models import AllFieldsModel, ExampleModel, SecretFieldModel


class ExampleSerializer(serializers.ModelSerializer):
Expand All @@ -23,3 +23,13 @@ class Meta:
"is_active",
"tags",
)


class SecretFieldSerializer(serializers.ModelSerializer):
secret_external = serializers.CharField(write_only=True)

class Meta:
model = SecretFieldModel
fields = ("title", "secret", "secret_external")

extra_kwargs = {"secret": {"write_only": True}}
11 changes: 9 additions & 2 deletions tests/testapp/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from drf_excel.mixins import XLSXFileMixin
from drf_excel.renderers import XLSXRenderer

from .models import AllFieldsModel, ExampleModel
from .serializers import AllFieldsSerializer, ExampleSerializer
from .models import AllFieldsModel, ExampleModel, SecretFieldModel
from .serializers import AllFieldsSerializer, ExampleSerializer, SecretFieldSerializer


class ExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
Expand All @@ -19,3 +19,10 @@ class AllFieldsViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
serializer_class = AllFieldsSerializer
renderer_classes = (XLSXRenderer,)
filename = "al_fileds.xlsx"


class SecretFieldViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
queryset = SecretFieldModel.objects.all()
serializer_class = SecretFieldSerializer
renderer_classes = (XLSXRenderer,)
filename = "secret.xlsx"
3 changes: 2 additions & 1 deletion tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from rest_framework import routers

from .testapp.views import AllFieldsViewSet, ExampleViewSet
from .testapp.views import AllFieldsViewSet, ExampleViewSet, SecretFieldViewSet

router = routers.SimpleRouter()
router.register(r"examples", ExampleViewSet)
router.register(r"all-fields", AllFieldsViewSet)
router.register(r"secret-field", SecretFieldViewSet)

urlpatterns = router.urls

0 comments on commit 63c0ac7

Please sign in to comment.