Отсутствие данных с помощью модели сериализации с помощью ManyToManyField

62
6

Вот примеры, которые я имею:

models.py:

class Example(models.Model):
title = models.CharField(...)
description = models.CharField(...)

class Foo(models.Model):
example = models.ManyToManyField(Example)

serializers.py:

class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Foo
fields = '__all__'
depth = 1

views.py:

...
serialized_data = [FooSerializer(foo).data for foo in Foo.objects.all().get]

На выходе я получаю только Example ID, но есть ли способ получить поля заголовка и описания (подробности m2mfield)? Насколько я понимаю, Foo.objects.all().get просто не содержит этих данных, но, может быть, я мог бы как-то его получить и использовать? Я мог бы также перестроить модели, если это необходимо, но в настоящее время я использую m2mf из-за необходимости содержать несколько объектов, связанных с данными этой модели.

Обновить

models.py:

class Event(models.Model):
ts = models.BigIntegerField(editable=False)

class Foo(Event):
user = models.ForeignKey(User, ...)
example = *...(remains to be the same)*
foos = models.ForeignKey('self', **somemore** null=True)

serializers.py:

class EventSerializer(serializers.ModelSerializer):

class Meta:
model = Event
fields = '__all__'

def to_representation(self, instance):
result = {'ts': instance.ts}
if isinstance(instance, Foo):
result['foo'] = FooSerializer(instance).data
return result

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username')

class FooSerializer(serializers.ModelSerializer):
# user = UserSerializer(read_only=True) # with this I have an error: Got AttributeError when attempting to get a value for field 'username' on #serializer 'UserSerializer'

class Meta:
model = Foo
fields = '__all__'
depth = 1

спросил(а) 2021-01-19T16:43:23+03:00 3 месяца, 2 недели назад
1
Решение
76

Вы можете использовать атрибут depth для достижения желаемого результата.

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

class FooSerializer(serializers.ModelSerializer):
class Meta:
model = Foo
fields = '__all__'
depth = 1



Помимо ответа, я хотел бы изменить ваш views.py код, потому что он кажется очень плохим :( Сделайте это на DRF Way as

serialized_data = FooSerializer(Foo.objects.all(), many=True).data<br>

Пример просмотра

from rest_framework.viewsets import ModelViewSet

class FooViewset(ModelViewSet):
serializer_class = FooSerializer
queryset = Foo.objects.all()


UPDATE-1

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
exclude = ('password',) # add fields that are need to be excluded

class FooSerializer(serializers.ModelSerializer):
user = UserSerializer()

class Meta:
model = Foo
fields = '__all__'
depth = 1

depth = 1 будет сериализовать все поля в model, (так же, как установка fields=='__all__' в мета-классе сериализатора)


ОБНОВЛЕНИЕ-2

class FooSerializer(serializers.ModelSerializer):
user = UserSerializer()

class Meta:
model = Foo
fields = '__all__'
depth = 1

def to_representation(self, instance):
real_data = super().to_representation(instance).copy()
# DO YOUR EXTRA CHECKS
child = UserSerializer(instance.child_foo).data
if child:
real_data.update({"child_data": child})
# After your checks, add it to "real_data"
return real_data

и я предположил, что у меня есть модель Foo как

class Foo(models.Model):
example = models.ManyToManyField(Example)
user = models.ForeignKey(User)
child_foo = models.ForeignKey('self', null=True, blank=True)

ответил(а) 2021-01-19T16:43:23+03:00 3 месяца, 2 недели назад
63

В вашем сериализаторе добавьте глубину = 1. Пример, где "пользователи" относятся к соответствующему полю:


FooSerializer(serializers.ModelSerializer):
class Meta:
model = Foo
fields = ('id', 'account_name', 'users', 'created')
depth = 1

ответил(а) 2021-01-19T16:43:23+03:00 3 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема