Как сериализовать связанную модель на глубине 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
Вернуться на верх