我正在尝试更新我的drf项目中的序列化器,使其以嵌套方式显示。有问题的两个模型是图像和画廊,图像与画廊有关。
我尝试关注https://www.django-rest-framework.org/api-guide/relations/#nested-relationships,但我不确定为什么它不起作用。
下面是models.py
class Gallery(models.Model):
title = models.CharField(max_length=30)
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True, blank=True)
modified_on = models.DateTimeField(auto_now=True, blank=True)
def __str__(self):
return self.title
class Image(models.Model):
gallery_id = models.ForeignKey(Gallery, on_delete=models.CASCADE)
img = models.ImageField(upload_to='images/')
created_on = models.DateTimeField(auto_now_add=True, blank=True)
serializers.py
class ImageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Image
fields = ["gallery_id", "img", "created_on", "id"]
class GallerySerializer(serializers.HyperlinkedModelSerializer):
image = ImageSerializer(many=True, read_only=True)
def validate(self, data):
# Check if user id is equal object id before creation or if SuperUser
request = self.context.get("request")
if request.user.id != data["author"].id and request.user.is_superuser is not True:
raise ValidationError("Unauthorized User Post")
return data
class Meta:
model = Gallery
fields = ["title", "author", "created_on", "modified_on", "image", "id"]
期望结果会
[
{
"title": "test_1",
"author": "http://127.0.0.1:8000/api/users/2/",
"created_on": "2019-08-19T09:13:45.107658Z",
"modified_on": "2019-08-19T09:13:45.107731Z",
"image": [
{
"gallery_id": "http://127.0.0.1:8000/api/galleries/24/",
"img": "http://127.0.0.1:8000/media/images/angga-tantama-background-art-minimalism.jpg",
"created_on": "2019-08-20T09:17:31.790901Z",
"id": 6
},
{
"gallery_id": "http://127.0.0.1:8000/api/galleries/24/",
"img": "http://127.0.0.1:8000/media/images/art-vector-background-illustration-minimalism-angga-tantam-2.jpg",
"created_on": "2019-08-20T09:31:40.505035Z",
"id": 7
}
]
"id": 24
},
{
"title": "test_2",
"author": "http://127.0.0.1:8000/api/users/2/",
"created_on": "2019-08-20T09:42:09.448974Z",
"modified_on": "2019-08-20T09:42:09.449042Z",
"id": 27
}
]
答案 0 :(得分:0)
image = ImageSerializer(many=True, read_only=True, source='image_set')
或
image_set = ImageSerializer(many=True, read_only=True) # use image_set in fields list too.
假设您有一个与此类似的Gallery
对象:
g = Gallery.objects.get(pk=1)
现在,与给定Galley
对象相关的所有图像的查询集将为:
Image.objects.filter(gallery_id=g) # g is the gallery object
在Django中,我们可以将其简化为:
g.image_set # same as Image.objects.filter(gallery_id=g)
现在问题来了,这个神奇的image_set
是从哪里来的。在Django ORM中,如果您可以在模型的ForeignKey中使用related_name来查询相关对象,例如:
gallery_id = models.ForeignKey(Gallery, on_delete=models.CASCADE, related_name='something')
# if you do this in your models.py then to get all images of a gallery you will now do:
g.something
但是由于您没有在related_name
中指定ForeginKey
,因此默认为model name all lowercase + _set
,因此在这种情况下为image_set
。
这是指向docs的链接。
如果您从模型中为同一模型指定了两个ForeignKey,则django也会要求您添加related_name
(在进行迁移时),因为它只能默认使用一个字段的相关名称。
这称为reverse_relationship。 forward_relationship
将是您执行以下操作的时间:
img = Image.objects.get(pk=1)
img.gallery_id # get the gallery object related to the image
这非常简单,因为gallery_id
是模型中的一个字段。
_id
来命名ForeignKey字段,这会引起误解。 img.gallery_id
不是Gallery的ID,而是整个Gallery对象。 Django在数据库中使用尾随ID保存“相关”字段,因此,在您的情况下,数据库中的列名称将为gallery_id_id
(很可能在新版本中可能已更改)。gallery_id
时:
img.gallery_id # the gallery object
img.gallery_id.id # actual id of the gallery
img.gallery_id_id # actual id of the gallery
但是,如果您只为gallery
命名字段,
img.gallery # the gallery object
img.gallery.id # actual id of the gallery
img.gallery_id # actual id of the gallery
哪个更清楚。
image_set
是模型类的属性了。而且drf在字段名称中查找模型属性,因此您可以使字段名称与属性(image_set
)相同,也可以使用序列化程序的source
参数指定属性。
答案 1 :(得分:0)
要正常工作,您需要使用source keyword
指定序列化程序应在何处获取数据。在您的情况下,这应该可以解决问题。
class GallerySerializer(serializers.HyperlinkedModelSerializer):
image = ImageSerializer(source="image_set", many=True, read_only=True)
def validate(self, data):
# Check if user id is equal object id before creation or if SuperUser
request = self.context.get("request")
if request.user.id != data["author"].id and request.user.is_superuser is not True:
raise ValidationError("Unauthorized User Post")
return data
class Meta:
model = Gallery
fields = ["title", "author", "created_on", "modified_on", "image", "id"]
如果在FK声明中使用了“ related_name”,则应使用此反向相关的名称。
如您所料,有许多Image
实例,我强烈建议您将字段命名为images
而不是image
我还建议您看看permission,而不是将逻辑带入序列化器。