Django Rest Framework:计算具有多个 ManyToManyField 值的对象数
Django Rest Framework: Count Number of Objects with multiple ManyToManyField values
在下面的示例中,我有两个具有 ManyToMany 关系的模型,我正在尝试计算与标签相关的 post 的数量。
有3个标签:体育、电影、健康
有 3 个 post:1 个用于运动,1 个用于电影,1 个 post 带有两个标签(运动和健康)
我可以获得每个标签的 posts 的计数,如下所示:
[
{
"name": "Sports",
"posts": 2
},
{
"name": "Films",
"posts": 1
},
{
"name": "Health",
"posts": 1
}
]
我的需求是针对标签的组合分别统计对象。因此,理想的输出是:
[
{
"name": "Sports",
"posts": 1
},
{
"name": "Films",
"posts": 1
},
{
"name": "Sports & Health",
"posts": 1
}
]
这就是我卡住的地方。我如何组合这两个标签,然后计算具有这两个标签的 post 对象的数量?
models.py
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.title
serializers.py
class TagSerializer(serializers.ModelSerializer):
posts = serializers.SerializerMethodField()
class Meta:
model = Tag
fields = ('name', 'posts')
def get_posts(self, obj):
posts = obj.post_set.all().count()
return posts
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
在您的 serializers.py get_posts
中使用它
Post.objects.filter(tags__in=[obj]).count()
而不是
obj.post_set.all().count()
目前,我通过计算前端 API 结果中每个标签的对象数量,设法找到了一个可行的解决方案。它适用于我的情况,因为返回的数据并不大。
let tagDict = {}
let data = response.data
for (let i = 0; i < data.length; i++) {
let key = data[i].name
if ( key in tagDict ) {
tagDict[key] += 1
} else {
tagDict[key] = 1
}
}
将此标记为已接受,直到出现更好的解决方案。
我建议在 Post 模型中为多对多关系添加一个相关字段,以便从标签端调用多对多关系。
tags = models.ManyToManyField(标签, related_name="posts_objects")
无需添加 SerializerMethodField,您只需 posts_objects.count 在序列化程序中即可:
class TagSerializer(serializers.ModelSerializer):
posts_objects = serializers.HiddenField()
posts = serializers.IntegerField(source="posts_objects.count", read_only=True)
class Meta:
model = Tag
fields = ('name', 'posts_objects', 'posts')
在下面的示例中,我有两个具有 ManyToMany 关系的模型,我正在尝试计算与标签相关的 post 的数量。
有3个标签:体育、电影、健康
有 3 个 post:1 个用于运动,1 个用于电影,1 个 post 带有两个标签(运动和健康)
我可以获得每个标签的 posts 的计数,如下所示:
[
{
"name": "Sports",
"posts": 2
},
{
"name": "Films",
"posts": 1
},
{
"name": "Health",
"posts": 1
}
]
我的需求是针对标签的组合分别统计对象。因此,理想的输出是:
[
{
"name": "Sports",
"posts": 1
},
{
"name": "Films",
"posts": 1
},
{
"name": "Sports & Health",
"posts": 1
}
]
这就是我卡住的地方。我如何组合这两个标签,然后计算具有这两个标签的 post 对象的数量?
models.py
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.title
serializers.py
class TagSerializer(serializers.ModelSerializer):
posts = serializers.SerializerMethodField()
class Meta:
model = Tag
fields = ('name', 'posts')
def get_posts(self, obj):
posts = obj.post_set.all().count()
return posts
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
在您的 serializers.py get_posts
中使用它Post.objects.filter(tags__in=[obj]).count()
而不是
obj.post_set.all().count()
目前,我通过计算前端 API 结果中每个标签的对象数量,设法找到了一个可行的解决方案。它适用于我的情况,因为返回的数据并不大。
let tagDict = {}
let data = response.data
for (let i = 0; i < data.length; i++) {
let key = data[i].name
if ( key in tagDict ) {
tagDict[key] += 1
} else {
tagDict[key] = 1
}
}
将此标记为已接受,直到出现更好的解决方案。
我建议在 Post 模型中为多对多关系添加一个相关字段,以便从标签端调用多对多关系。
tags = models.ManyToManyField(标签, related_name="posts_objects")
无需添加 SerializerMethodField,您只需 posts_objects.count 在序列化程序中即可:
class TagSerializer(serializers.ModelSerializer):
posts_objects = serializers.HiddenField()
posts = serializers.IntegerField(source="posts_objects.count", read_only=True)
class Meta:
model = Tag
fields = ('name', 'posts_objects', 'posts')