Как создать пользовательский сериализатор для DRF APIView для получения списка записей вместо идентификаторов

Я создаю API для программы маркировки картинок. Картинка (ресурс) может иметь метки или verified_labels - если более одного пользователя ввели метку для одного и того же ресурса. Я пытаюсь расширить программу, добавив ввод табу. Табу означает, что эти метки были введены наиболее часто для определенного ресурса.

В настоящее время моими моделями являются Resource, Label и VerifiedLabel.

models.py

class Resource(models.Model):
    id = models.PositiveIntegerField(null=False, primary_key=True)
    hash_id = models.CharField(max_length=256)
    creators = models.ManyToManyField(Creator)
    titles = models.ManyToManyField(Title)
    created_start = models.DateField(null=True)
    created_end = models.DateField(null=True)
    location = models.CharField(max_length=512, null=True)
    institution_source = models.CharField(max_length=512, blank=True)
    institution = models.CharField(max_length=512, blank=True)
    origin = models.URLField(max_length=256, null=True)
    enabled = models.BooleanField(default=True)
    media_type = models.CharField(max_length=256, default='picture')

    objects = models.Manager()

    def __str__(self):
        return self.hash_id or ''

    @property
    def verified_labels(self):
        verified_labels = self.labels.values('verified_label').annotate(count=Count('label'))

        return verified_labels.values('verified_label_id', 'verified_label__name', 'verified_label__language', 'count')

class VerifiedLabel(models.Model):
    name = models.CharField(max_length=256)
    language = models.CharField(max_length=256)

    objects = models.Manager()

    def __str__(self):
        return self.name or ''


class Label(models.Model):
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True)
    gameround = models.ForeignKey(Gameround, on_delete=models.CASCADE)
    resource = models.ForeignKey(Resource, on_delete=models.CASCADE, related_name='labels')
    verified_label = models.ForeignKey(VerifiedLabel, on_delete=models.CASCADE)
    created = models.DateTimeField(editable=False)
    score = models.PositiveIntegerField(default=0)
    origin = models.URLField(max_length=256, blank=True, default='')

    objects = models.Manager()

    def __str__(self):
        return str(self.verified_label) or ''

    def save(self, *args, **kwargs):
        if not self.id:
            self.created = timezone.now()

        return super().save(*args, **kwargs)

У меня есть сериализатор для каждой модели, но для представления я использую этот сериализатор, который в основном сериализует объект ресурса и извлекает taboo_labels для этого объекта.

Моя основная проблема заключается в том, что вместо Label происходит обращение к VerifiedLabel, а мне нужно отсортировать наиболее используемые метки. В таблице VerifiedLabel все имена уникальны, поэтому я не могу отсортировать наиболее используемые.

serializers.py

class TabooLabelSerializer(serializers.ModelSerializer):
  creators = CreatorSerializer(many=True)
  titles = TitleSerializer(many=True)
  taboo_labels = serializers.SerializerMethodField('get_taboo_tags')

  class Meta:
    model = Resource
    fields = ['id', 'hash_id', 'titles', 'creators', 'taboo_labels']
    read_only_fields = ['titles', 'creators', 'institution']

  def get_taboo_labels(self, res):
    """

    :param res:
    :return: A list of the most used labels per Resource
    """
    # TODO: Filter out most used labels and return text instead of id
    taboo_labels = res.tags.values_list('tag', flat=True)

    return taboo_labels

  def to_representation(self, data):
    data = super().to_representation(data)
    return data

Моя вторая проблема заключается в том, что я хочу, чтобы в объекте JSON в браузере возвращался текст, а не идентификаторы.

views.py

class GameResourceView(APIView):
    """
    API view to handle resources
    """
    serializer_class = TabooLabelSerializer

    def get_queryset(self):
        resource = None
        random_resource_idx = None
        while resource is None:
            while resource is None:
                while random_resource_idx is None:
                    while not Resource.objects.all().filter(id=random_resource_idx).exists():
                        random_number = random.randint(0, Resource.objects.count() - 1)
                        if not Resource.objects.all().filter(id=random_number).exists():
                            random_number_alternative = random.randint(0, Resource.objects.count() - 1)
                            if Resource.objects.all().filter(id=random_number_alternative).exists():
                                random_resource_idx = random_number_alternative
                            else:
                                random_resource_idx = random_number
                    resource = Resource.objects.all().filter(id=random_resource_idx)
        return resource

    def get(self, request, *args, **kwargs):
        resource = self.get_queryset()
        serializer = TabooLabelSerializer(resource, many=True)
        return Response({
            'resource and labels': serializer.data
        })

В основном я хочу следующее:

{
    "resource and labels to combine": [
        {
            "some resource data "
                }
            ],
            "taboo_labels": [
                'boat',
                'horse',
                'lake'
            ]
        }
    ]
}

и то, что я получаю в настоящее время это:

{
    "resource and labels to combine": [
        {
            "some resource data "
                }
            ],
            "taboo_labels": [
                62,
                195,
                133
            ]
        }
    ]
}
Вернуться на верх