Skip to content

Commit ffc3ca3

Browse files
Ensure that ModelSerializer fields are in same order than in DRF (#1182)
* fix(ModelSerializer): preserve field order like DRF * test(ModelSerializer): add test_get_field_names * docs: update changelog and authors files --------- Co-authored-by: Oliver Sauder <os@esite.ch>
1 parent a45c475 commit ffc3ca3

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Adam Wróbel <https://adamwrobel.com>
22
Adam Ziolkowski <adam@adsized.com>
33
Alan Crosswell <alan@columbia.edu>
44
Alex Seidmann <alex@leanpnt.de>
5+
Antoine Auger <https://antoineauger.fr/en>
56
Anton Shutik <shutikanton@gmail.com>
67
Arttu Perälä <arttu@perala.me>
78
Ashley Loewen <github@ashleycodes.tech>

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ any parts of the framework not mentioned in the documentation should generally b
1313
### Fixed
1414

1515
* Fixed OpenAPI schema generation for `Serializer` when used inside another `Serializer` or as a child of `ListField`.
16+
* `ModelSerializer` fields are now returned in the same order than DRF
1617

1718
### Removed
1819

rest_framework_json_api/serializers.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,11 @@ def get_field_names(self, declared_fields, info):
309309
"""
310310
meta_fields = getattr(self.Meta, "meta_fields", [])
311311

312-
declared = {}
313-
for field_name in set(declared_fields.keys()):
314-
field = declared_fields[field_name]
315-
if field_name not in meta_fields:
316-
declared[field_name] = field
312+
declared = {
313+
field_name: field
314+
for field_name, field in declared_fields.items()
315+
if field_name not in meta_fields
316+
}
317317
fields = super().get_field_names(declared, info)
318318
return list(fields) + list(getattr(self.Meta, "meta_fields", list()))
319319

tests/test_serializers.py

+34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
from django.db import models
3+
from rest_framework.utils import model_meta
34

45
from rest_framework_json_api import serializers
56
from tests.models import DJAModel, ManyToManyTarget
@@ -50,3 +51,36 @@ class ReservedFieldNamesSerializer(serializers.Serializer):
5051
"ReservedFieldNamesSerializer uses following reserved field name(s) which is "
5152
"not allowed: meta, results"
5253
)
54+
55+
56+
def test_get_field_names():
57+
class MyTestModel(DJAModel):
58+
verified = models.BooleanField(default=False)
59+
uuid = models.UUIDField()
60+
61+
class AnotherSerializer(serializers.Serializer):
62+
ref_id = serializers.CharField()
63+
reference_string = serializers.CharField()
64+
65+
class MyTestModelSerializer(AnotherSerializer, serializers.ModelSerializer):
66+
an_extra_field = serializers.CharField()
67+
68+
class Meta:
69+
model = MyTestModel
70+
fields = "__all__"
71+
extra_kwargs = {
72+
"verified": {"read_only": True},
73+
}
74+
75+
# Same logic than in DRF get_fields() method
76+
declared_fields = MyTestModelSerializer._declared_fields
77+
info = model_meta.get_field_info(MyTestModel)
78+
79+
assert MyTestModelSerializer().get_field_names(declared_fields, info) == [
80+
"id",
81+
"ref_id",
82+
"reference_string",
83+
"an_extra_field",
84+
"verified",
85+
"uuid",
86+
]

0 commit comments

Comments
 (0)