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
}
]
}
read_only_fields
and that doesn't seem to make any differenceMy question: How do I get the identifier field within the validated_data of the nested representation?
我的问题是:如何在嵌套表示的validated_data中获得标识符字段?
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')
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的序列化器,则应该为嵌套标签创建另一个序列化器。