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

时间:2018-07-29 20:19:36

标签: django django-rest-framework mongoengine

这是我的MSV:

models.py

CN_NOTIFY

serializers.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)

views.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__'

我正在发送以下json对象:

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
        )

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

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

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

编辑

我希望两个文档都是动态的,因为某些json可能包含名称和值无法预测的字段,因此我也必须保存它们,因此我将两个模型类都动态化了。但是,我可以展开{ "_id" : ObjectId("5b5e201c540d1c3b7a4491e8"), "name" : "Helmut", "age" : 21, "is_married" : true, "address" : [ { "country" : "Germany", "town" : "Berlin" } ] } ,但不能对PersonInfoModel做同样的事情。 PersonAddressModel字段不会显示在数据库(MongoDB)中。 另一方面,我希望地址列表中的某些字段为必填字段。

1 个答案:

答案 0 :(得分:1)

在您的 PersonAddressModel 中,您仅定义了两个字段,分别是countrytown。这意味着,在DB中,您使用这两个字段定义了架构,street不包括在内。 因此,请更改模型以添加额外的字段,例如

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

更新
如果您的address字段是动态的,并且像dict这样的字段,则使用mongoengine.fields.DictField()作为

import mongoengine


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


Update-2
您可以在 PersonSerializer 中以{p>

from rest_framework_mongoengine import serializers
from rest_framework import serializers as drf_serializer


class PersonSerializer(serializers.DynamicDocumentSerializer):
    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

    class Meta:
        model = PersonModel
        fields = '__all__'

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

UPDATE-3
为了引发验证错误,您必须将True传递给.is_valid()(ref doc-field level validation)方法,就像

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(True) # Change is here <<<<
            serializer.save()

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

        return Response(
            status=status.HTTP_201_CREATED
        )