如何计算Django中model_set的区别?

时间:2018-07-18 03:54:44

标签: django django-models django-rest-framework django-serializer

我研究了这个question,但我认为是不同的。 让我进一步解释一下。我有一个名为DetailTrackSerializer的序列化程序来序列化我的Track模型,并且在TaggedSerializer中嵌套了一个DetailTrackSerializer

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)

3 个答案:

答案 0 :(得分:1)

从您的Tagged中我了解到 Data Redundancy 的可能性很大,这就是您的tagged_set多次显示的原因。
我要说的是,这不是您的序列化器的Representation Problem ,而不是它是您的模型的Implementation Problem 。 br />
因此,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)

    class Meta:
        unique_together = ('track', 'tag')

更改模型后,请执行makemigrationsmigration

注意:在进行migration时,您可能会遇到django.db.utils.IntegrityError: UNIQUE constraint failed的异常情况。因此,删除Tagged模型中的所有条目

答案 1 :(得分:0)

Edwin Harly,在“跟踪”,“标记”和“标记”模型之间有一些数据重叠。如果您接受,建议删除标记的模型。如果要保存哪个用户创建标签,请在标签模型中添加用户字段。

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',)

答案 2 :(得分:0)

通读Django有关https://dev.to/claireparker/reasons-not-to-use-ids-in-css-4ni4的文档后,这就是我想出的解决方案

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": []
        },