热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在验证过程中丢失字段-嵌套序列化器create()-losingfieldsduringvalidation-nestedserializercreate()

Idontunderstandwhyspecificfieldsarebeingdroppedwithinvalidated_data.我不理解为什么在validated_da

I don't understand why specific fields are being dropped within validated_data.

我不理解为什么在validated_data中删除特定字段。

When POSTing input to create() a new instance, the following line: thisLabel = ClassificationLabel.objects.get(identifier=label.identifier) throws an error because the identifier attribute is not present:

在发布要创建()一个新实例的输入时,如下一行:thisLabel = ClassificationLabel.objects.get(identifier=label.identifier)会抛出一个错误,因为标识符属性不存在:

AttributeError at /api/v1/policies/ 

'collections.OrderedDict' object has no attribute 'identifier

的集合。OrderedDict的对象没有属性标识符。

I have the following serializers within Django REST framework:

我在Django REST框架中有以下序列化器:

serializers.py:

serializers.py:

class ClassificationLabelDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = ClassificationLabel
        fields = ('displayName', 'helpText', 'identifier', 'backgroundColour', 'foregroundColour', 'comment', 'description', 'lastChanged', 'revision')
        read_only_fields = ('identifier', 'lastChanged', 'revision',)


class PolicySerializer(serializers.ModelSerializer):
    labels = ClassificationLabelDetailSerializer(many=True)

    class Meta:
        model = Policy
        fields = ('displayName', 'identifier', 'labels', 'lastChanged', 'description', 'comment')
        read_only_fields = ('identifier', 'lastChanged',)

    def create(self,validated_data):
        labelData = validated_data.pop('labels')
        thisPolicy = Policy.objects.create(**validated_data)
        for label in labelData:
            for k, v in label.items():
                print(k, v)
            thisLabel = ClassificationLabel.objects.get(identifier=label.identifier)#insert organisational filter here
            PolicyMemberClassificationLabel.objects.create(policy=thisPolicy, label=thisLabel, order=index)
        return thisPolicy

models.py:

models.py:

class ClassificationLabel(models.Model):
    displayName = models.CharField(max_length = 32)
    helpText = models.TextField(max_length = 140, blank=True)
    backgroundColour = models.CharField(max_length=8)
    foregroundColour = models.CharField(max_length=8)
    description = models.TextField(max_length = 256, blank=True)
    comment = models.TextField(max_length = 1024, blank=True)
    lastChanged = models.DateTimeField(auto_now=True, editable=False)
    identifier = models.CharField(max_length = 128, blank=True, editable=False)
    revision = models.PositiveIntegerField(default=1, editable=False)

    def __str__(self):
        return self.displayName + " - " + self.identifier

    def save(self, *args, **kwargs):
        self.revision += 1
        #the following code generates a unique identifier and checks it for collisions against existing identifiers
        if not self.identifier:
            stringCheck = False
            while stringCheck is False:
                newString = str(uuid.uuid4())
                newString.replace('-', '')
                doesStringExist = ClassificationLabel.objects.filter(identifier=newString).exists()
                if doesStringExist is False:
                    stringCheck = True
            self.identifier = newString
        super(ClassificationLabel, self).save(*args, **kwargs) # Call the "real" save() method.


class Policy(models.Model):
    description = models.TextField(max_length = 256, blank=True)
    comment = models.TextField(max_length = 1024, blank=True)
    lastChanged = models.DateTimeField(auto_now =True)
    displayName = models.CharField(max_length = 64)
    identifier = models.CharField(max_length = 128, blank=True)
    labels = models.ManyToManyField(ClassificationLabel, through='PolicyMemberClassificationLabel')
    revision = models.PositiveIntegerField(default=1)

    class Meta:
        verbose_name_plural = 'Policies'

    def __str__(self):
        return self.displayName + " - " + self.identifier

    def save(self, *args, **kwargs):
        self.revision += 1
        #the following code generates a unique identifier and checks it for collisions against existing identifiers
        if not self.identifier:
            stringCheck = False
            while stringCheck is False:
                newString = str(uuid.uuid4())
                newString.replace('-', '')
                doesStringExist = Policy.objects.filter(identifier=newString).count()
                if doesStringExist == 0:
                    stringCheck = True
            self.identifier = newString
            super(Policy, self).save() # Call the "real" save() method.


class PolicyMemberClassificationLabel(models.Model):
    label = models.ForeignKey(ClassificationLabel, related_name='memberLabels')
    policy = models.ForeignKey(Policy, related_name='parentPolicy')
    order = models.PositiveSmallIntegerField(blank=True)

when sending the following via POST it's dropping the identifier, lastChanged and revision fields from the nested representation within validated_data.

当通过POST发送以下内容时,它将从validated_data中的嵌套表示中删除标识符、lastChanged和修订字段。

{
  "labels": [
    {
      "displayName": "Test name",
      "helpText": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book. Wayfarers sartorial authentic, small batch readymade disrupt col",
      "identifier": "fa27e9bd-5007-4874-b10c-46b63c7c8a86",
      "backgroundColour": "#808900",
      "foregroundColour": "#000000",
      "comment": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book.",
      "description": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book.",
      "lastChanged": "2017-07-03T09:26:20.450681Z",
      "revision": 2
    },
    {
      "displayName": "Test name 1",
      "helpText": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book.",
      "identifier": "29c968dd-8b83-4374-962d-32b9ef527e1b",
      "backgroundColour": "#9f0500",
      "foregroundColour": "#FFFFFF",
      "comment": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book.",
      "description": "Wayfarers sartorial authentic, small batch readymade disrupt coloring book.",
      "lastChanged": "2017-07-03T09:25:52.955293Z",
      "revision": 2
    }
  ]
}
  • I can see that the serializer .is_valid() is True for the PolicySerializer
  • 我可以看到serializer .is_valid()对于PolicySerializer是正确的。
  • when I look at validated_data those three fields are missing (the rest are there)
  • 当我查看validated_data时,这三个字段会丢失(其余的字段都在那里)
  • I've tried commenting out the read_only_fields and that doesn't seem to make any difference
  • 我尝试过注释read_only_fields,但这似乎没有什么区别
  • I've been referencing the DRF documentation here
    • I've ensured that the client's content-type is set correctly, since there was a similar problem here
    • 我已经确保正确地设置了客户机的内容类型,因为这里有一个类似的问题
    • other people seem to be having similar problems
    • 其他人似乎也有类似的问题
  • 我在这里引用了DRF文档,我确保了客户机的内容类型设置正确,因为这里有类似的问题,其他人似乎也有类似的问题。

My question: How do I get the identifier field within the validated_data of the nested representation?

我的问题是:如何在嵌套表示的validated_data中获得标识符字段?

2 个解决方案

#1


0  

Fields which have editable set to False on the model are read_only by default on serializer. [http://www.django-rest-framework.org/api-guide/serializers/#specifying-read-only-fields]

在模型上具有可编辑设置为False的字段在序列化器上默认为read_only。[http://www.django-rest-framework.org/api-guide/serializers/ specifying-read-only-fields]

You should use a different serializer for creation where the field will be given explicitly like so:

您应该使用不同的序列化器进行创建,其中字段将被显式地指定为:

class ClassificationLabelDetailSerializer(serializers.ModelSerializer):
    identifier = serializers.CharField()

    class Meta:
        model = ClassificationLabel
        fields = ('displayName', 'helpText', 'backgroundColour', 'foregroundColour', 'comment', 'description', 'lastChanged', 'revision')

#2


1  

In ClassificationLabelDetailSerializer you have set identifier as a read_only field, and the documentation states:

在ClassificationLabelDetailSerializer中,您将标识符设置为read_only字段,文档说明如下:

Read-only fields are included in the API output, but should not be included in the input during create or update operations.

只读字段包含在API输出中,但不应该包含在创建或更新操作期间的输入中。

This means they do not get passed to validated_data as they should not be used for write operations.

这意味着它们不会被传递给validated_data,因为它们不应该用于写操作。

Remove identifier from the read_only fields and it should work. If you need that serializer elsewhere with identifier as read_only, you should then create another serializer for the nested labels.

从read_only字段中删除标识符,它应该可以工作。如果需要在其他地方使用标识符作为read_only的序列化器,则应该为嵌套标签创建另一个序列化器。


推荐阅读
author-avatar
牛玺峻国_781
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有