Django Rest Framework: количество объектов с несколькими значениями ManyToManyField - PullRequest
0 голосов
/ 20 февраля 2020

В приведенном ниже примере у меня есть две модели с отношением ManyToMany, и я пытаюсь подсчитать количество сообщений, связанных с тегами.


Есть 3 тега: Спорт, Фильмы, Здоровье
Есть 3 сообщения: 1 для Спорта, 1 для Фильмов и 1 сообщение с двумя тегами (Спорт и Здоровье)
Я могу получить количество сообщений для каждый тег, как показано ниже:
[
    {
        "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
    }

]

Вот где я застрял. Как мне объединить два тега, а затем посчитать количество объектов записей, имеющих оба этих тега?

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__'

Ответы [ 2 ]

0 голосов
/ 27 февраля 2020

В настоящее время мне удалось получить рабочее решение, подсчитав количество объектов для каждого тега в результате 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 
        }   
    }   

Отметьте это как принятое, пока не будет найдено лучшее решение.

0 голосов
/ 20 февраля 2020

используйте это в вашем serializers.py get_posts

Post.objects.filter(tags__in=[obj]).count()

вместо

obj.post_set.all().count()

...