Доступ к значениям Django M2M в наборе запросов без циклов

Я получаю некоторые данные через Ajax, что позволяет мне сделать некоторую фильтрацию на модели, которая имеет некоторые m2m отношения (скажем, Model). Я получаю набор запросов, скажем "content", который мне нужно отправить обратно, используя json. Вот упрощенные строки кода:

content =  Models.objects.all()
content = content.values
return JsonResponse({"data":list(content)})

Все работало нормально, но проект изменился, и теперь мне нужно включить значения некоторых m2m связанных моделей, присоединенных к Model, в каждый экземпляр результата queryset, проблема в том, что content=Model.objects.all(), конечно, не даст мне эти значения без некоторого цикла, поэтому я застрял. Я помню, что использовал опцию глубины в DRF, которая могла бы сделать эту работу здесь, но, к сожалению, я не могу сделать это сейчас, так как проект слишком продвинутый и живой. Есть ли способ добавить непосредственно в набор запросов результаты значений, связанных с m2m? Большое спасибо

Добавляем сюда упрощенные модели :

class Content(models.Model):
    uuid = models.CharField(max_length=255, primary_key=True, default=uuid.uuid4, editable=False)
    pathology = models.ManyToManyField(Pathology, null=True, blank=True)
    organs = models.ManyToManyField(Organ, null=True, blank=True)
    title = models.CharField(verbose_name="Titre",
                              max_length=255, null=True, blank=False)
    document = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    description = RichTextField(null=True, blank=True)

class Pathology(models.Model):
    title = models.CharField(max_length=255, null=True, blank=True)

    def __str__(self):
        return self.title

class Organ(models.Model):
    title = models.CharField(max_length=255, null=True, blank=True)

    def __str__(self):
        return self.title

Пожалуйста, не используйте .values(…) [Django-antipatterns], они разрушают логику в слое модели. Кроме того, вы не можете использовать .values(…) двунаправленно: вы можете только преобразовывать записи в словари, но не десериализовывать словари в объекты модели.

В PostgreSQL можно использовать ArrayAgg [Django-doc], это агрегат, который работает только для PostgreSQL, и, кроме того, он, вероятно, не идеален, поскольку опять же делает адаптацию процесса сериализации громоздкой. Вы можете использовать это как:

from django.contrib.postgres.aggregates import ArrayAgg

content = Models.objects.values().annotate(
    organs=ArrayAgg('organs__pk')
)
return JsonResponse({"data":list(content)})

Использование Django REST framework все же возможно с текущим представлением. Вы можете установить этот фреймворк и определить сериализатор с помощью:

from rest_framework import serializers

class ContentSerializer(serializers.ModelSerializer):
    organs = serializers.PrimaryKeyRelatedField(many=True)
    
    class Meta:
        model = Content
        fields = '__all__'

Затем в представлении вы можете работать с:

contents = Models.objects.prefetch_related('organs')
serializer = ContentSerializer(contents, many=True)
return JsonResponse({'data': serializer.data})

Решение Виллема с использованием DRF корректно, но возвращает только ID связанных полей. Я полагаю, что есть способ изменить это и получить другое поле, но вместо этого я нашел другой способ, не требующий переопределения:

class OrganSerializer(serializers.ModelSerializer):
    class Meta:
        model = Organ
        fields = (('title'),)

class PathologySerializer(serializers.ModelSerializer):
    class Meta:
        model = Pathology
        fields = (('title'),)

class ContentSerializer(serializers.ModelSerializer):
    organs = OrganSerializer(many=True, read_only=True)
    pathology = PathologySerializer(many=True, read_only=True)
    
    class Meta:
        model = Content
        fields = '__all__'
     

Остальная часть решения была точной. Я еще не пробовал PGSQL для продов

Вернуться на верх