django rest框架多个外键序列化

Posted

技术标签:

【中文标题】django rest框架多个外键序列化【英文标题】:django rest framework multiple foreign keys serializing 【发布时间】:2017-01-07 01:19:39 【问题描述】:

起初看起来很简单,现在我很困惑。我写了数据结构,现在很难得到它。到目前为止我所拥有的:

class Area(models.Model):
    name = models.CharField(max_length=128)
    ...

class Category(models.Model):
    name = models.CharField(max_length=128)
    ....

class Venue(models.Model):
    name = models.CharField(max_length=128)
    category = models.ForeignKey(Category, related_name='venues')
    area = models.ForeignKey(Area, related_name='venues')

我需要根据Area pk 获取包含场地的类别。是否可以使用 django rest 框架来做到这一点?结果应该类似于:

  
    "pk": 1,
    "name": "London",
    "categories": [
        
             "pk": 1,
             "name": "Bars",
             "venues": [
                 
                      "pk": 1,
                      "name": "Cool bar"
                 ,
                 
                      "pk": 2,
                      "name": "Cooler bar"
                 ,
                 
                      "pk": 3,
                      "name": "Coldest bar"
                 ,
            ]
        
    ]


理想情况下我需要这样的东西:

class VenueSerializer(serializers.ModelSerializer):
  .....

class CategorySerializer(serializers.ModelSerializer):
    venues = VenueSerializer(read_only=True, many=True)

    class Meta:
        model = Category
        fields = ('pk', 'name', 'venues', )

class AreaSerializer(serializers.ModelSerializer):
    categories = CategorySerializer(read_only=True, many=True)

    class Meta:
        model = Area
        fields = ('pk', 'name', 'categories', )

但这当然行不通,因为AreaCategory 没有直接 相关。所以我的问题是,是否可以在不改变数据结构的情况下做到这一点?

【问题讨论】:

【参考方案1】:

有点难看,但是如果你设置在对象模型上,你可以使用DRF's SerializerMethodField来做到这一点。

您的 Area 序列化程序将如下所示:

class AreaSerializer(serializers.ModelSerializer):
    categories = SerializerMethodField()

    def get_categories(self, obj):
        # this will find all categories with a venue in given area
        categories = Category.objects.filter(venues__area=obj)
        serializer = CategorySerializer(categories, many=True)
        return serializer.data

    class Meta:
        model = Area
        fields = ('pk', 'name', 'categories', )

如果不进行优化,这种结构会产生大量的数据库查询。我建议使用Django's prefetch_related 操作来减少冗余查询的数量。

【讨论】:

以上是关于django rest框架多个外键序列化的主要内容,如果未能解决你的问题,请参考以下文章

如何在序列化程序 django rest 框架中为外键设置源

当父记录存在时,如何在 django rest 框架的子序列化程序中设置外键值

使用 django-rest-framework 序列化程序检索外键值

在序列化程序中编辑外键字段 - Django Rest Framework

Django rest框架嵌套序列化程序创建方法

Django rest 框架深度序列化器仅在 to_representation 中