问题描述
我有两个模型,
class Book(AppModel):
title = models.CharField(max_length = 255)
class Link(AppModel):
link = models.CharField(max_length = 255)
class Page(AppModel):
book = models.ForeignKey( Book,related_name = pages,on_delete = models.CASCADE)
链接= models.ForeignKey( Link,related_name = pages,on_delete = models.CASCADE)
page_no = models.IntegerField()
text = models.TextField()
和 serializers
class LinkSerializer(serializers.ModelSerializer):
类Meta:
模型=链接
字段= ['link']
类PageSerializer(serializers.ModelSerializer):
类Meta:
模型=页面
字段=('link','text','page_no')
def validate_text(self,value):
#一些验证在这里完成。
def validate_link(self,value):
#一些验证在这里完成。
类BookSerializer(serializers.ModelSerializer):
页= PageSerializer(很多=真)
类元:
模型=书籍
字段=(' title','pages')
@ transaction.atomic
def create(self,validated_data):
pages_data = validated_data.pop('pages')
书= self.Meta.model.objects.create(** validated_data)
用于pages_data中的page_data:
Page.objects.create(book = book,** page_data)
返回书
<$ c $中有一个 validate_text
方法c> PageSerializer 。 create
方法将永远不会调用 PageSerializer
和 page_data
所以我尝试了另一种方法:
@ transaction.atomic
def create(self,validated_data):
pages_data = validated_data.pop('pages')
book = self.Meta.model.objects.create(** validated_data)
用于pages_data中的page_data:
page = Page(book = book)
page_serializer = PageSerializer(page,data = page_data)
如果page_serializer.is_valid():
page_serializer.save()
其他:
提高serializers.ValidationError(page_serializer.errors)
返回书
发布的数据:
{
title: Book Title,
pages:[{
link:1, page_no:52, text: sometext}]
}
但是上述方法会引发错误:
{
link:[
类型错误。预期的pk值,已收到链接。
]
}
我也找到了为什么导致此错误:尽管我发布的数据是 pk
值 1
的 Link
,当数据从 BookSerializer
传递到 PageSerializer
时,显示如下: { link: / go_to_link /, page_no:52, text: sometext}
为什么将 Link
的实例传递给 PageSerializer
,而我发送的却是 pk
的 Link
?需要帮助。
要使用嵌套序列化程序来验证嵌套对象:
@ transaction.atomic
def create(self,validated_data) :
pages_data = validated_data.pop('pages')#一本书的页面数据
book = self.Meta.model.objects.create(** validated_data)
用于pages_data中的page_data:
页面=页面(book = book)
page_serializer = PageSerializer(page,data = page_data)
如果page_serializer.is_valid():#PageSerializer进行验证
page_serializer.save()
否则:
引发serializers.ValidationError(page_serializer .errors)#如果有任何
归还书
,则抛出错误假设您将数据发送为:
{
title:书名,
页面:[{
link:2,#< =这里的这个
page_no:52,
text: sometext}]
}
在上述数据中,我们发送了<$ c $的 id
c>链接对象。但是在上面定义的 BookSerializer
的 create
方法中,我们发送的数据更改为:
{
title:书名,
页面:[{
link:链接对象(2),#< =更改为ID为2的链接对象
page_no:52,
text: sometext}]
}
PageSerializer
实际上是为了接收<$ c 链接
的$ c> pk 值,即 link:2
链接:链接对象(2)
。因此它会引发错误:
{
link:[
类型错误。预期的pk值,已收到链接。
]
}
因此,解决方法是覆盖 因此,您的 和父级序列化器: ,则会引发错误,这应该允许嵌套的序列化程序进行验证,而不是在父序列化器的create方法内部编写验证并违反DRY。 I have two models as: and There is a So I tried another approach as: Posted data: But the above approach throws error: I also found why this error is caused: Though I am posting data with Why is an Instance of To validate a nested object using a nested serializer: Suppose you send the data as: In the above data we are sending an And the So the workaround is to override the So your and the parent serializer: That should allow the nested serializer to do the validation instead of writing validation inside the create method of the parent serializer and violating DRY. 这篇关于Django Rest Framework:仅在自定义验证之后,如何将数据传递给嵌套的序列化器并创建对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! to_internal_value $ c嵌套序列化程序的$ c>方法将接收到的
链接对象(2)
对象转换为其 pk
值。 / p>
PageSerializer
类应为:
class PageSerializer(serializers.ModelSerializer):
类元:
模型=页面
字段=('link','text','page_no')
def to_internal_value(self,data):
link_data = data.get( link)
if isinstance(link_data,Link):#如果接收到对象
data [ link] = link_data.pk#更改为其pk值
obj = super(PageSerializer,self).to_internal_value(data)
return obj
def validate_text (自我,价值):
#一些验证在这里完成。
def validate_link(self,value):
#一些验证在这里完成。
class BookSerializer(serializers.ModelSerializer):
页= PageSerializer(很多=真)
类元:
模型=图书
字段=(' title','pages')
@ transaction.atomic
def create(self,validated_data):
pages_data = validated_data.pop('pages')#a的页面数据book
book = self.Meta.model.objects.create(** validated_data)
用于pages_data中的page_data:
page = Page(book = book)
page_serializer = PageSerializer( page,data = page_data)
如果page_serializer.is_valid():#PageSerializer进行验证
page_serializer.save()
否则:
引发serializers.ValidationError(page_serializer.errors) #如果有任何
归还书
class Book(AppModel):
title = models.CharField(max_length=255)
class Link(AppModel):
link = models.CharField(max_length=255)
class Page(AppModel):
book= models.ForeignKey("Book",related_name="pages",on_delete=models.CASCADE)
link = models.ForeignKey("Link", related_name="pages", on_delete=models.CASCADE)
page_no = models.IntegerField()
text = models.TextField()
serializers
class LinkSerializer(serializers.ModelSerializer):
class Meta:
model = Link
fields = ['link']
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
fields = ('link','text','page_no')
def validate_text(self, value):
#some validation is done here.
def validate_link(self, value):
#some validation is done here.
class BookSerializer(serializers.ModelSerializer):
pages = PageSerializer(many=True)
class Meta:
model = Book
fields = ('title','pages')
@transaction.atomic
def create(self, validated_data):
pages_data= validated_data.pop('pages')
book = self.Meta.model.objects.create(**validated_data)
for page_data in pages_data:
Page.objects.create(book=book, **page_data)
return book
validate_text
method in PageSerializer
. The create
method will never call the PageSerializer
and the page_data
is never validated.@transaction.atomic
def create(self, validated_data):
pages_data = validated_data.pop('pages')
book= self.Meta.model.objects.create(**validated_data)
for page_data in pages_data:
page = Page(book=book)
page_serializer = PageSerializer(page, data = page_data)
if page_serializer.is_valid():
page_serializer.save()
else:
raise serializers.ValidationError(page_serializer.errors)
return book
{
"title": "Book Title",
"pages": [{
"link":1,"page_no":52, "text":"sometext"}]
}
{
"link": [
"Incorrect type. Expected pk value, received Link."
]
}
pk
value 1
of a Link
, the data when passed to the PageSerializer
from the BookSerializer
appears as such: {"link": "/go_to_link/", "page_no":52, "text": "sometext"}
Link
passed to the PageSerializer
whereas what I sent is pk
of Link
? NEED hELP HERE.@transaction.atomic
def create(self, validated_data):
pages_data = validated_data.pop('pages') #pages data of a book
book= self.Meta.model.objects.create(**validated_data)
for page_data in pages_data:
page = Page(book=book)
page_serializer = PageSerializer(page, data = page_data)
if page_serializer.is_valid(): #PageSerializer does the validation
page_serializer.save()
else:
raise serializers.ValidationError(page_serializer.errors) #throws errors if any
return book
{
"title": "Book Title",
"pages": [{
"link":2,#<= this one here
"page_no":52,
"text":"sometext"}]
}
id
of the Link
object. But in the create
method of the BookSerializer
defined above, the data we sent changes to:{
"title": "Book Title",
"pages": [{
"link":Link Object (2),#<= changed to the Link object with id 2
"page_no":52,
"text":"sometext"}]
}
PageSerializer
is actually meant to receive an pk
value of the link
i.e, "link": 2
instead of "link":Link Object (2)
. Hence it throws error:{"link": [ "Incorrect type. Expected pk value, received Link." ]}
to_internal_value
method of the nested serializer to convert the received Link Object (2)
object to its pk
value.PageSerializer
class should then be:class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
fields = ('link','text','page_no')
def to_internal_value(self, data):
link_data = data.get("link")
if isinstance(link_data, Link): #if object is received
data["link"] = link_data.pk # change to its pk value
obj = super(PageSerializer, self).to_internal_value(data)
return obj
def validate_text(self, value):
#some validation is done here.
def validate_link(self, value):
#some validation is done here.
class BookSerializer(serializers.ModelSerializer):
pages = PageSerializer(many=True)
class Meta:
model = Book
fields = ('title','pages')
@transaction.atomic
def create(self, validated_data):
pages_data = validated_data.pop('pages')#pages data of a book
book= self.Meta.model.objects.create(**validated_data)
for page_data in pages_data:
page = Page(book=book)
page_serializer = PageSerializer(page, data = page_data)
if page_serializer.is_valid(): #PageSerializer does the validation
page_serializer.save()
else:
raise serializers.ValidationError(page_serializer.errors) #throws errors if any
return book