如何计算 Django 中 model_set 的不同?
How to count the distinct of model_set in Django?
我已经研究过这个 ,但我认为它有所不同。
让我进一步解释一下。我有一个名为 DetailTrackSerializer
的序列化程序来序列化我的 Track
模型,并且我在 DetailTrackSerializer
中嵌套了一个 TaggedSerializer
。
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tagged_set = TaggedSerializer(many=True)
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tagged_set',)
class TaggedSerializer(serializers.ModelSerializer):
tag = TagSerializer()
class Meta:
model = Tagged
fields = ('tag',)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name',)
目前,这个 DetailTrackSerializer
正在返回一个像这样的 json
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tagged_set": [
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
...
等等,如果这个曲目中有 100 个 "punk rock" 标签,它将出现 100 次,并且可能还有另一个标签也不仅仅是 "punk rock"。我需要的是这样的东西
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tagged_set": [
{
"tag": {
"id": 1356,
"name": "punk rock"
},
"frequency": 100,
},
{
"tag": {
"id": 546,
"name": "pop"
},
"frequency": 236,
},
...
每个标签只出现一次,并且有频率。
注意:我也在使用 Django Rest Framework
编辑:models.py
class Tagged(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
track = models.ForeignKey(Track, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
class Track(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
link = models.URLField(max_length=255, blank=True)
tags = models.ManyToManyField(Tag, through='Tagged', blank=True)
Edwin Harly,Track、Tag 和 Tagged 模型之间有一些数据重叠。如果您接受,我建议您删除标记模型。如果要保存哪个用户创建标签,请在标签模型中添加用户字段。
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
class Track(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
link = models.URLField(max_length=255, blank=True)
tags = models.ManyToManyField(Tag, through='Tagged', blank=True)
然后,您可以像这样使用序列化程序:
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tags = TagSerializer(many=True)
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tags',)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name',)
从你的Tagged
我了解到Data Redundancy
的可能性很大,这就是你的tagged_set
多次出现的原因。
我想说的是,这不是 Representation Problem
与你的序列化程序 ,而不是 它是 Implementation Problem
与你的模型.
所以,unique_together
属性将解决问题,因为
class Tagged(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
track = models.ForeignKey(Track, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
<b>class Meta:
unique_together = ('track', 'tag')</b>
更改模型后,请执行makemigrations
和migration
。
注意:在执行 migration
时,您可能会遇到 django.db.utils.IntegrityError: UNIQUE constraint failed
异常。因此,删除 Tagged
模型
中的所有条目
阅读 Django 关于 querysets 的文档后,这是我想出的解决方案
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tags_frequency = serializers.SerializerMethodField()
artist = ArtistSerializer()
def get_tags_frequency(self, track):
tags = track.tags.all()
return tags.values('id', 'name').annotate(Count('id'))
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tags_frequency',)
这将给我 json 这样的表示
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tags_frequency": [
{
"name": "punk rock",
"id": 1356,
"id__count": 100
},
{
"name": "punk",
"id": 1357,
"id__count": 60
}
]
},
{
"id": 169,
"artist": {
"id": 164,
"name": "Jeff And Sheri Easter"
},
"title": "The Moon And I (Ordinary Day Album Version)",
"link": "",
"tags_frequency": []
},
我已经研究过这个 DetailTrackSerializer
的序列化程序来序列化我的 Track
模型,并且我在 DetailTrackSerializer
中嵌套了一个 TaggedSerializer
。
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tagged_set = TaggedSerializer(many=True)
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tagged_set',)
class TaggedSerializer(serializers.ModelSerializer):
tag = TagSerializer()
class Meta:
model = Tagged
fields = ('tag',)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name',)
目前,这个 DetailTrackSerializer
正在返回一个像这样的 json
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tagged_set": [
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
{
"tag": {
"id": 1356,
"name": "punk rock"
}
},
...
等等,如果这个曲目中有 100 个 "punk rock" 标签,它将出现 100 次,并且可能还有另一个标签也不仅仅是 "punk rock"。我需要的是这样的东西
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tagged_set": [
{
"tag": {
"id": 1356,
"name": "punk rock"
},
"frequency": 100,
},
{
"tag": {
"id": 546,
"name": "pop"
},
"frequency": 236,
},
...
每个标签只出现一次,并且有频率。 注意:我也在使用 Django Rest Framework
编辑:models.py
class Tagged(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
track = models.ForeignKey(Track, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
class Track(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
link = models.URLField(max_length=255, blank=True)
tags = models.ManyToManyField(Tag, through='Tagged', blank=True)
Edwin Harly,Track、Tag 和 Tagged 模型之间有一些数据重叠。如果您接受,我建议您删除标记模型。如果要保存哪个用户创建标签,请在标签模型中添加用户字段。
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
class Track(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
link = models.URLField(max_length=255, blank=True)
tags = models.ManyToManyField(Tag, through='Tagged', blank=True)
然后,您可以像这样使用序列化程序:
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tags = TagSerializer(many=True)
artist = ArtistSerializer()
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tags',)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name',)
从你的Tagged
我了解到Data Redundancy
的可能性很大,这就是你的tagged_set
多次出现的原因。
我想说的是,这不是 Representation Problem
与你的序列化程序 ,而不是 它是 Implementation Problem
与你的模型.
所以,unique_together
属性将解决问题,因为
class Tagged(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
track = models.ForeignKey(Track, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
<b>class Meta:
unique_together = ('track', 'tag')</b>
更改模型后,请执行makemigrations
和migration
。
注意:在执行 migration
时,您可能会遇到 django.db.utils.IntegrityError: UNIQUE constraint failed
异常。因此,删除 Tagged
模型
阅读 Django 关于 querysets 的文档后,这是我想出的解决方案
class DetailTrackSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=120)
link = serializers.URLField(max_length=120)
tags_frequency = serializers.SerializerMethodField()
artist = ArtistSerializer()
def get_tags_frequency(self, track):
tags = track.tags.all()
return tags.values('id', 'name').annotate(Count('id'))
class Meta:
model = Track
fields = ('id', 'artist', 'title', 'link', 'tags_frequency',)
这将给我 json 这样的表示
{
"tracks": [
{
"id": 168,
"artist": {
"id": 163,
"name": "Gob"
},
"title": "Face the Ashes",
"link": "",
"tags_frequency": [
{
"name": "punk rock",
"id": 1356,
"id__count": 100
},
{
"name": "punk",
"id": 1357,
"id__count": 60
}
]
},
{
"id": 169,
"artist": {
"id": 164,
"name": "Jeff And Sheri Easter"
},
"title": "The Moon And I (Ordinary Day Album Version)",
"link": "",
"tags_frequency": []
},