Как получить только связанные объекты в сериализаторе django с помощью manyToMany?

class BookingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Booking
        fields = "__all__"


class EmployeeSerializer(serializers.ModelSerializer):
    bookings_st = BookingSerializer(many=True, read_only=True)

    class Meta:
        model = Employee
        fields = "__all__"


class ProjectSerializer(serializers.ModelSerializer):
    employees = EmployeeSerializer(read_only=True, many=True)

    class Meta:
        model = Project
        fields = "__all__"
class Employee(models.Model):
    name = models.CharField(max_length=127)
    lastname = models.CharField(max_length=127)


class Project(models.Model):
    title = models.CharField(max_length=127)
    employees = models.ManyToManyField(Employee,
                                       related_name='employees')

class Booking(models.Model):
    start = models.DateField()
    end = models.DateField()
    employee = models.ForeignKey(Employee,
                                 on_delete=models.CASCADE,
                                 related_name='bookings_st')
    project = models.ForeignKey(Project,
                                on_delete=models.CASCADE,
                                related_name='bookings_st')

Я получаю вложенный объект, но как получить в Emploee только связанные с обоими (проектом и сотрудником) бронирования? Сейчас я просто получаю все заказы, которые есть у этого сотрудника. Я имею в виду такую структуру: проект_1: emploee_1: [bookings_that_belong_to_THIS_PROJECT]

Здесь можно использовать SerializerMethodField вместе с объектом сериализатора context:

class BookingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Booking
        fields = "__all__"


class EmployeeSerializer(serializers.ModelSerializer):
    bookings_st = serializers.SerializerMethodField()

    def get_bookings_st(self, employee):
        project = self.context.get("project")
        return BookingSerializer(
            employee.bookings_st.filter(project=project), 
            many=True,
        ).data

    class Meta:
        model = Employee
        fields = "__all__"


class ProjectSerializer(serializers.ModelSerializer):
    employees = serializers.SerializerMethodField()

    def get_employees(self, project):
        return EmployeeSerializer(
            project.employees.all(),
            many=True,
            context={**self.context, "project": project}
        ).data

    class Meta:
        model = Project
        fields = "__all__"

Это не будет суперпроизводительным, если вы используете это при составлении списка проектов или при получении конкретного проекта с большим количеством сотрудников. В зависимости от вашего сценария использования - если вы используете его только для получения конкретного проекта, например, вы можете использовать prefetch_related и класс Prefetch для предварительной выборки пользовательских наборов запросов сотрудников + бронирований, отфильтровывая конкретный проект (и вы можете затем использовать обычные сериализаторы).

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