我不明白为什么在validated_data中删除特定字段。
当POST输入到create()一个新实例时,以下行:
thisLabel = ClassificationLabel.objects.get(identifier=label.identifier)
因为标识符属性不存在而抛出错误:
AttributeError at /api/v1/policies/
'collections.OrderedDict' object has no attribute 'identifier
我在Django REST框架中有以下序列化程序:
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:
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)
通过POST发送以下内容时,它会从validated_data中的嵌套表示中删除标识符,lastChanged和revision字段。
{
"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
并且似乎没有任何区别我的问题:如何在嵌套表示的validated_data中获取标识符字段?
答案 0 :(得分:1)
在ClassificationLabelDetailSerializer
中,您已将identifier
设置为read_only
字段,文档说明:
只读字段包含在API输出中,但不应该包含 在创建或更新操作期间包含在输入中。
这意味着它们不会传递给validated_data
,因为它们不应该用于写操作。
从identifier
字段中删除read_only
,它应该有效。如果您需要identifier
作为read_only
的其他位置的序列化程序,则应为嵌套标签创建另一个序列化程序。
答案 1 :(得分:0)
默认情况下,序列化程序上模型上editable
设置为False
的字段为read_only
。 [http://www.django-rest-framework.org/api-guide/serializers/#specifying-read-only-fields]
您应该使用不同的序列化程序进行创建,其中将明确指定字段:
class ClassificationLabelDetailSerializer(serializers.ModelSerializer):
identifier = serializers.CharField()
class Meta:
model = ClassificationLabel
fields = ('displayName', 'helpText', 'backgroundColour', 'foregroundColour', 'comment', 'description', 'lastChanged', 'revision')