Django:序列化程序过滤掉未声明的字段

Django: Serializers filtering out undeclared fields

这是我的 MSV:

models.py

import mongoengine


class PersonAddressModel(mongoengine.DynamicEmbeddedDocument):
    country = mongoengine.fields.StringField()
    town = mongoengine.fields.StringField()


class PersonModel(mongoengine.DynamicDocument):
    name = mongoengine.fields.StringField()
    age = mongoengine.IntField()
    is_married = mongoengine.fields.BooleanField()
    address = EmbeddedDocumentListField(PersonAddressModel)

serializers.py

from rest_framework_mongoengine import serializers
from .models import PersonInfoModel, PersonAddressModel
import mongoengine


class PersonAddressSerializer(serializers.EmbeddedDocumentSerializer):

    class Meta:
        model = PersonAddressModel
        fields = '__all__'


class PersonSerializer(serializers.DynamicDocumentSerializer):

    class Meta:
        model = PersonModel
        fields = '__all__'

views.py

from rest_framework_mongoengine import viewsets
from .serializers import PersonSerializer, PersonAddressSerializer
from rest_framework.response import Response
from rest_framework import status
import djongo
from .models import PersonModel


class PersonView(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = PersonSerializer

    def create(self, request):
        serializer = self.serializer_class(data=request.data)

        try:
            serializer.is_valid()
            serializer.save()

        except djongo.sql2mongo.SQLDecodeError:
            return Response(
                status=status.HTTP_503_SERVICE_UNAVAILABLE
            )

        return Response(
            status=status.HTTP_201_CREATED
        )

我要发送以下 json 对象:

{
    "name": "Helmut",
    "age": 21,
    "is_married": true,
        "address": [{"country": "Germany", "town": "Berlin", "street": "Wolfstraße 1"}]
}

然而,当我检查数据库时,我看到以下对象:

{
    "_id" : ObjectId("5b5e201c540d1c3b7a4491e8"),
    "name" : "Helmut",
    "age" : 21,
    "is_married" : true,
    "address" : [
        {
            "country" : "Germany",
            "town" : "Berlin"
        }
    ]
}

也就是说,Helmut的街道不见了。我想知道为什么!我敢打赌它与序列化程序有关,但我无法弄清楚它到底是什么。

编辑

我希望我的两个文档都是动态的,因为某些 json 可能包含名称和值不可预测的字段,我也必须保存它们,所以我将两个模型 类 设为动态.但是我可以扩展 PersonInfoModel 但不能对 PersonAddressModel 做同样的事情。 street 字段不会出现在数据库中 (MongoDB)。 另一方面,我希望地址列表中的某些字段是必需的。

在您的 PersonAddressModel 中,您只定义了两个字段,即 countrytown。这意味着,在 DB 中,您使用这两个字段定义了模式,street 不包括在内。 因此,更改您的模型以添加额外的字段,如

class PersonAddressModel(mongoengine.DynamicEmbeddedDocument):
    country = mongoengine.fields.StringField()
    town = mongoengine.fields.StringField()
    <b>street = mongoengine.fields.StringField()</b>

更新
如果您的 address 字段是动态的并且它是一个类似字典的字段,那么使用 mongoengine.fields.DictField() as,

import mongoengine


class PersonModel(mongoengine.DynamicDocument):
    name = mongoengine.fields.StringField()
    age = mongoengine.IntField()
    is_married = mongoengine.fields.BooleanField()
    <b>address = mongoengine.fields.DictField()</b>


更新 2
你可以在 PersonSerializer 中做一个 field level validation 作为,

from rest_framework_mongoengine import serializers
<b>from rest_framework import serializers as drf_serializer</b>


class PersonSerializer(serializers.DynamicDocumentSerializer):
    <b>def validate_address(self, address):
        required_fields = ['street', 'country']
        if not all([True for field in required_fields if field in address]):
            raise drf_serializer.ValidationError('some required fields are missing')
        return address</b>

    class Meta:
        model = PersonModel
        fields = '__all__'

由于 rest_framework_mongoengine 没有 ValidationError class,我们使用 DRF's ValidationError class

UPDATE-3
为了引发验证错误,您必须将 True 传递给 .is_valid() (reff doc - Raising an exception on invalid data) 方法,如

class PersonView(viewsets.ModelViewSet):
    lookup_field = 'id'
    serializer_class = PersonSerializer

    def create(self, request):
        serializer = self.serializer_class(data=request.data)

        try:
            <b>serializer.is_valid(True) # Change is here <<<<</b>
            serializer.save()

        except djongo.sql2mongo.SQLDecodeError:
            return Response(
                status=status.HTTP_503_SERVICE_UNAVAILABLE
            )

        return Response(
            status=status.HTTP_201_CREATED
        )