首页 > 解决方案 > 使用 Django Rest Framework 序列化相关枢轴模型

问题描述

我正在学习 Django,并且正在使用 Django Rest Framework。在我的应用程序中,我有三种不同的模型

这是定义不同模型的方式:

class Bar(models.Model):
    name = models.CharField(max_length=60)
    location = models.PointField()
    address = models.CharField(max_length=60)
    description = models.TextField(default='')

    beers = models.ManyToManyField('api.Beer', through='api.BarBeer')

class Beer(models.Model):
    name = models.CharField(max_length=60)
    alcohol = models.FloatField(default=0)

class BarBeer(models.Model):
    bar = models.ForeignKey(Bar, on_delete=models.CASCADE)
    beer = models.ForeignKey(Beer, on_delete=models.CASCADE)

    price = models.FloatField(default=0)
    type = EnumField(Type, default=Type.Cask)
    volume = models.IntegerField(default=0)

现在我想用该特定酒吧的所有啤酒序列化一个给定的酒吧,包括枢轴模型中的额外字段BarBeer。例如,下面是我想要的输出(注意啤酒上额外的三个字段,来自 BarBeer 模型):

{
    "id": 1,
    "name": "A bar",
    "beers": [
        {
            "id": 1,
            "name": "Ship Full of IPA",
            "alcohol": 6.5,
            "type": "bottle",
            "price": "35",
            "volume": "33"
        }
    ]
}

我不知道如何从数据透视模型中获取额外字段作为序列化输出的一部分。这就是我的序列化程序现在的样子:

class BarDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bar
        fields = ('id', 'name', 'beers')
        depth = 3

标签: djangodjango-rest-framework

解决方案


首先beers = models.ManyToManyField('api.Beer', through='api.BarBeer')这个字段是不必要的,因为你已经创建了一个名为BarBeer. ManyToManyField 意味着添加额外的表。所以,如果我们假设这个字段不存在而你有BarBeer table,你可以使用BarBeerSerializer这样的方法来做到这一点:

序列化程序.py

class BarBeerSerializer(serializers.ModelSerializer):
    name = serializers.SerializerMethodField()
    alchol = serializers.SerializerMethodField()

    class Meta:
        model = BarBeer
        fields = ['id','name','alchol','type','price','volume']

    def get_name(self,obj):
        return obj.beer.name

    def get_alchol(self,obj):
       return obj.beer.alchol


class BarSerializer(serializers.ModelSerializer):
    beers = serializers.SerializerMethodField()
    class Meta:
        model = Bar
        fields = ['id', 'name', 'beers']

    def get_beers(self,obj:Bar):
        beers = obj.barbeer_set.all()
        return BarBeerSerializer(beers,many=True).data

如果有错误,请在评论中提出。


推荐阅读