Django Rest Framework-过滤嵌套关系的字段

问题描述

我想返回CustomerImage对象的嵌套表示,其中Customer可以有许多Images

当前,GET请求从Image查询集中为每个Customer对象返回 ALL 个图像列表,如下所示。 如何只显示列表中每个Image对象的相关Customer(s)?

# The 'images' field currently returns all images rather than related images to the customer id.
[
   {
       'id': 1,'name': 'John Doe','images': [
           {'id': 1,'name': 'foo.jpg','customer': 1},{'id': 2,'name': 'bar.jpg','customer': 2},{'id': 3,'name': 'foobar.jpg','customer': 3},...
       ]
   },{
       'id': 2,'name': 'Jane Doe',...
]

这是我当前的设置

示例模型

class Customer(models.Model):
      name = models.CharField()

class Image(models.Model):
      name = models.CharField()
      customer = models.ForeignKey(
        Customer,on_delete=models.CASCADE)

示例序列化器

class CustomerSerializer(serializers.ModelSerializer):
    # My Customer nested relationship is expressed using ImageSerializer as a field
    images = ImageSerializer(many=True)

    class Meta:
        model = Customer
        fields = ('id','name','images')
        read_only_fields = ('id',)

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = '__all__'
        read_only_fields = ('id',)

如果我的问题不清楚,请让我知道,我将更新我的问题。谢谢。

解决方法

您需要使用相关名称作为反向外键的字段。

在您的情况下,应该是

class CustomerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Customer
        fields = ('id','name','image_set')
        read_only_fields = ('id',)

将其视为反向FK查询-Customer.objects.first().image_set.all()


有关此的DRF文档在这里; Reverse Relations

关于反向关系的Django文档为here


使用_set反向查找是django的默认设置。您可能会在关系中添加自己的related_name

django文档中的示例;

# Declare the ForeignKey with related_query_name
class Tag(models.Model):
    article = models.ForeignKey(
        Article,on_delete=models.CASCADE,related_name="tags",related_query_name="tag",)
    name = models.CharField(max_length=255)

# That's now the name of the reverse filter
Article.objects.filter(tag__name="important")

对于您的示例,您可以添加类似内容;

class Image(models.Model):
    name = models.CharField()
    customer = models.ForeignKey(
        Customer,related_name="images"
    )

django默认值Customer.image_set仍然有效,但是您可以执行Customer.images.all(),因为您已为关系定义了related_name