Оптимизация вложенных сериализаторов DRF

Помогите, плиз, оптимизировать чудовищный код в сериализаторе, который очень медленно работает... Как я понимаю, основная проблема в нескольких SerializerMethodFields, где вызываются get_tasks (). Подскажите, пожалуйста, как правильно сделать здесь - в init загрузить все задачи, которые есть в self.tasks. А в методе to_representation все 4 ключа вызова SerializerMethodField - equipment_types, recovery_days, completed_days, work_in_progress_days? И самое главное - как правильно оптимизировать вызов вложенных сериализаторов?

Самое главное - как правильно оптимизировать вызов вложенных сериализаторов?

Вот некоторые предложения по оптимизации кода в вашем сериализаторе:

  1. Предварительно загрузите все задачи экземпляра MonthPlan в метод init MonthPlanViewSerializer, а не вызывайте метод get_tasks для каждого поля SerializerMethodField. Это позволит избежать ненужных запросов к базе данных для каждого поля.

  2. В методе to_representation вызовите соответствующий метод для каждого поля SerializerMethodField (например, get_recovery_days) и сохраните результат в локальной переменной, а не вызывайте метод несколько раз.

  3. Для вложенных сериализаторов (например, EquipmentTypeSerializer) можно использовать метод prefetch_related для предварительной загрузки связанных объектов при запросе к базе данных. Это может повысить производительность за счет уменьшения количества запросов к базе данных, необходимых для сериализации данных. Вот пример того, как вы можете применить эти предложения в своем коде:

    class MonthPlanViewSerializer(serializers.HyperlinkedModelSerializer):
    year_plan_id = serializers.PrimaryKeyRelatedField(
        queryset=YearPlan.objects.all(),
        source='year_plan.id'
    )
    equipment_id = serializers.PrimaryKeyRelatedField(
        queryset=Equipment.objects.all(),
        source='equipment.id',
        required=False
    )
    equipment = EquipmentSerializer(many=False, read_only=True)
    transport_id = serializers.PrimaryKeyRelatedField(
        queryset=Transport.objects.all(),
        source='transport.id',
        default=None
    )
    transport = TransportSerializer(many=False, read_only=True)
    equipment_types = serializers.SerializerMethodField()
    tasks = SimpleTaskSerializer(many=True, read_only=True)
    recovery_days = serializers.SerializerMethodField()
    completed_days = serializers.SerializerMethodField()
    work_in_progress_days = serializers.SerializerMethodField()

    # Preload all tasks for the MonthPlan instance in the __init__ method
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.tasks = self.instance.tasks.all()

    # Return the preloaded tasks
    def get_tasks(self, instance: MonthPlan):
        return self.tasks

    def get_work_in_progress_days(self, instance: MonthPlan) -> set:
        tasks = self.get_tasks(instance)
        return set(int(task.planned_date.strftime("%d")) for task in tasks if task.work_in_progress)

    def get_completed_days(self, instance: MonthPlan) -> list:
        return self.get_common_days(instance, 'is_completed')

    def get_recovery_days(self, instance: MonthPlan) -> list:
        return self.get_common_days(instance, 'is_broken')

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