Django - Аннотирование, фильтрация и сортировка по отношениям "один ко многим" не работает

Я работаю над таблицей, которая отображает список заказов с возможностью фильтрации и сортировки в зависимости от прямого атрибута заказа или косвенно от атрибута связанных моделей. Две модели, о которых идет речь, это Order и Block. Заказ может иметь не слишком много блоков, связанных с ним, а блок всегда имеет один уникальный заказ.

class Order(CustomBaseModel):

    date_of_order = models.DateField(default=timezone.now, verbose_name="Date of order"
    ...

class Block(CustomBaseModel):

    ...
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    ...

Чтобы иметь возможность фильтровать ордера с блоком или без блока, я аннотирую свой набор запросов следующим образом:

       order_queryset = Order.objects.all().annotate(
            is_material_available=Case(
                    When(block__isnull=False, then=Value(True)),
                    default=Value(False),
                    output_field=BooleanField()
                ),
        )

и затем используйте опцию фильтрации для новой аннотации:

        is_material_available = self.data["is_material_available"]

        if is_material_available == "True":
            order_queryset = order_queryset.filter(is_material_available=True)

        elif is_material_available == "False":
            order_queryset = order_queryset.filter(is_material_available=False)

Использование этого метода приводит к такому поведению:

  • is_material_available=="True": Выбирает только те заказы, у которых есть заказы, что замечательно, но полностью нарушает пагинацию. Допустим, количество заказов на странице равно 8, это создаст страницу только с одним заказом, или даже больше. Также некоторые заказы присутствуют на разных страницах.
  • is_material_available=="False": Получение заказов с блоками и без блоков, связанных с ним, но пагинация работает нормально.

Я попытался изменить фильтрацию, используя:

        order_queryset = order_queryset.filter(Exists(Block.objects.filter(order=OuterRef("pk")))

или

        order_queryset = order_queryset.filter(block__isnull=False)

или используя этот вариант:

        order_queryset = Order.objects.all().annotate(
            is_material_available=Count('block', distinct=True)
        )

        order_queryset = order_queryset.filter(is_material_available__gt=0)

но результат тот же. Сортировка с использованием аннотации "is_material_available" не работает и сортирует заказы случайным образом, хотя SQL-запрос выглядит нормально.

Кто-нибудь знает, что происходит?

Я выяснил, что было не так. Это не имеет никакого отношения к фреймворку queryset в django, а к тому, как ордера и блоки обновлялись из двух разных баз данных. Различные методы фильтрации работают нормально.

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