diff --git a/AUTHORS b/AUTHORS index fbd3fe6e..7f4a8237 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,6 +2,7 @@ Adam Wróbel Adam Ziolkowski Alan Crosswell Alex Seidmann +Antoine Auger Anton Shutik Arttu Perälä Ashley Loewen diff --git a/CHANGELOG.md b/CHANGELOG.md index 83b2e62d..3e69577b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ any parts of the framework not mentioned in the documentation should generally b ### Fixed * Fixed OpenAPI schema generation for `Serializer` when used inside another `Serializer` or as a child of `ListField`. +* `ModelSerializer` fields are now returned in the same order than DRF ### Removed diff --git a/rest_framework_json_api/serializers.py b/rest_framework_json_api/serializers.py index 4b619ac4..c680f60a 100644 --- a/rest_framework_json_api/serializers.py +++ b/rest_framework_json_api/serializers.py @@ -309,11 +309,11 @@ def get_field_names(self, declared_fields, info): """ meta_fields = getattr(self.Meta, "meta_fields", []) - declared = {} - for field_name in set(declared_fields.keys()): - field = declared_fields[field_name] - if field_name not in meta_fields: - declared[field_name] = field + declared = { + field_name: field + for field_name, field in declared_fields.items() + if field_name not in meta_fields + } fields = super().get_field_names(declared, info) return list(fields) + list(getattr(self.Meta, "meta_fields", list())) diff --git a/tests/test_serializers.py b/tests/test_serializers.py index e1b14ed8..9d4200a3 100644 --- a/tests/test_serializers.py +++ b/tests/test_serializers.py @@ -1,5 +1,6 @@ import pytest from django.db import models +from rest_framework.utils import model_meta from rest_framework_json_api import serializers from tests.models import DJAModel, ManyToManyTarget @@ -50,3 +51,36 @@ class ReservedFieldNamesSerializer(serializers.Serializer): "ReservedFieldNamesSerializer uses following reserved field name(s) which is " "not allowed: meta, results" ) + + +def test_get_field_names(): + class MyTestModel(DJAModel): + verified = models.BooleanField(default=False) + uuid = models.UUIDField() + + class AnotherSerializer(serializers.Serializer): + ref_id = serializers.CharField() + reference_string = serializers.CharField() + + class MyTestModelSerializer(AnotherSerializer, serializers.ModelSerializer): + an_extra_field = serializers.CharField() + + class Meta: + model = MyTestModel + fields = "__all__" + extra_kwargs = { + "verified": {"read_only": True}, + } + + # Same logic than in DRF get_fields() method + declared_fields = MyTestModelSerializer._declared_fields + info = model_meta.get_field_info(MyTestModel) + + assert MyTestModelSerializer().get_field_names(declared_fields, info) == [ + "id", + "ref_id", + "reference_string", + "an_extra_field", + "verified", + "uuid", + ]