Как сериализовать связанную модель на глубине 2 без сериализации промежуточной модели на глубине 1?
У меня есть три модели с внешними ключами в этом направлении Order -> Customer -> User
. Я хотел бы написать набор представлений для заказов, который сериализует соответствующего пользователя без промежуточного клиента.
Модели:
class Order(models.Model):
customer = ForeignKey("customers.Customer")
class Customer(models.Model):
user = ForeignKey("users.User")
class User(models.Model):
name = CharField(max_length=64)
Serializer:
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = ["name"]
class OrderSerializer(ModelSerializer):
user = UserSerializer(source="customer__user", read_only=True)
class Meta:
model = Order
fields = ["id", "user"]
Набор видов:
class OrderViewSet(ModelViewSet):
queryset = Order.objects.all()
serializer_class = OrderSerializer
Желаемый выход:
[
{"id": 1, "user": {"name": "John"}},
{"id": 2, "user": {"name": "Mary"}},
]
Фактический выход:
[
{"id": 1},
{"id": 2},
]
Если я прохожу через промежуточный сериализатор клиента, то все работает нормально:
class CustomerSerializer(ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = User
fields = ["user"]
class OrderSerializer(ModelSerializer):
customer = CustomerSerializer(read_only=True)
class Meta:
model = Order
fields = ["id", "customer"]
но затем в выходных данных содержится промежуточный объект клиента:
[
{"id": 1, {"customer": {"user": {"name": "John"}}},
{"id": 2, {"customer": {"user": {"name": "Mary"}}},
]
В source
используется синтаксис точек, поэтому:
class UserSerializer(ModelSerializer):
class Meta:
model = User
fields = ['name']
class OrderSerializer(ModelSerializer):
user = UserSerializer(source='customer.user', read_only=True)
class Meta:
model = Order
fields = ['id', 'user']
Я бы также посоветовал использовать .select_related(..)
в наборе представлений, чтобы избежать получения Customer
и User
с помощью дополнительных запросов, поэтому:
class OrderViewSet(ModelViewSet):
queryset = Order.objects.select_related('customer__user')
serializer_class = OrderSerializer