Django Graphene при фильтрации по вложенному значению, не показывать родительскую запись, если не возвращается никаких данных

У меня есть запрос GraphQL, который возвращает заказы на поставку и продукты, которые идут с этими заказами на поставку. Я настроил два фильтра, первый - по имени пользователя, связанному с заказом на покупку, а второй - по названию продукта для продуктов, входящих в заказы на покупку.

Если пользователь ищет определенный продукт, я хотел бы возвращать только те заказы, которые содержат этот продукт. В настоящее время он по-прежнему возвращает все заказы на покупку, но удаляет данные о товарах, которые не соответствуют критериям поиска.

Структура базы данных представляет собой таблицу, содержащую заказы на поставку, называемую purchase_orders и таблицу продуктов заказов на поставку, называемую purchase_orders_products, которая имеет FK, называемую order_id к полю id заказа на поставку.

Например, в приведенном ниже ответе, если purchaseOrdersProductsOrderId.edges пуст, мне не нужно возвращать данные заказа для ThisIsUsername.

Схема

# region Integration Purchase Orders
class PurchasesProducts(DjangoObjectType):
    id = graphene.ID(source='pk', required=True)

    class Meta:
        model = purchase_orders_products
        interfaces = (relay.Node,)
        filter_fields = {'product_name': ['icontains']}


class Purchases(DjangoObjectType):
    id = graphene.ID(source='pk', required=True)

    class Meta:
        model = purchase_orders
        interfaces = (relay.Node,)
        filter_fields = {'date': ['gt', 'lt', 'isnull'], 'username': ['icontains'],}
        connection_class = ArtsyConnection


class PurchasesQuery(ObjectType):
    purchases = ArtsyConnectionField(Purchases)
    date_filter_list = graphene.List(graphene.List(graphene.String))

    @staticmethod
    def resolve_date_filter_list(self, info, **kwargs):
        years = purchase_orders.objects.filter(user_id=info.context.user.id).annotate(year=ExtractYear('date'), month=ExtractMonth('date'),).order_by().values_list('year', 'month').order_by('-year', '-month').distinct()
        return years

    @staticmethod
    def resolve_purchases(self, info, date_filter=None, **kwargs):
        return purchase_orders.objects.filter(user_id=info.context.user.id).all().order_by("-date")


purchasesSchema = graphene.Schema(query=PurchasesQuery)
# endregion

Query

{
  dateFilterList
  purchases(first: 15, after: "") {
    pageCursors {
      ...
    }
    edges {
      node {
        id
        ...
        purchaseOrdersProductsOrderId (productName_Icontains: "access") {
          edges {
            node {
              id
              productId
              productName
              productNumber
            }
          }
        }
      }
    }
  }
}

Ответ

{
  "data": {
    "dateFilterList": [
      ...
    ],
    "purchases": {
      "pageCursors": {
        ...
      },
      "edges": [
        {
          "node": {
            "id": "ab0d9542-480a-4a99-8f49-3474e820beb0",
            "username": "ThisIsUsername",
            ...
            "purchaseOrdersProductsOrderId": {
              "edges": []
            }
          }
        },
        {
          "node": {
            "id": "03e937b2-5b67-4161-90de-cdeda8dcd065",
            "username": "barry1234",
            ...
            "purchaseOrdersProductsOrderId": {
              "edges": [
                {
                  "node": {
                    "id": "f9945e45-59ef-42e9-9b06-988f24d1c8ed",
                    "productId": "84fae6ca-8a16-45ee-b36f-31a0ba134866",
                    "productName": "Access Denied",
                    "productNumber": "47"
                  }
                }
              ]
            }
          }
        },
        ...

Вы должны определить фильтр для product_name в Purchases вместо PurchaseProducts. Самый простой способ сделать это - определить filterset_class. В моем примере я немного упростил запросы и использовал DjangoFilterConnectionField, потому что не знаю, что такое ArtsyConnectionField.

from django_filters import CharFilter, FilterSet

class PurchaseOrderFilter(FilterSet):
    class Meta:
        model = purchase_orders
        fields = {'date': ['gt', 'lt', 'isnull'], 'username': ['icontains'],}

    products__product_name = CharFilter(lookup_expr="icontains",)

class PurchaseOrderProductFilter(FilterSet):
    class Meta:
        model = purchase_orders_products
        fields = {"name": ["icontains"]}

class PurchasesProducts(DjangoObjectType):
    id = graphene.ID(source='pk', required=True)

    class Meta:
        model = purchase_orders_products
        interfaces = (graphene.relay.Node,)
        filterset_class = PurchaseOrderProductFilter


class Purchases(DjangoObjectType):
    id = graphene.ID(source='pk', required=True)
    products = DjangoFilterConnectionField(PurchasesOrderProduct)

    class Meta:
        model = purchases_orders
        interfaces = (graphene.relay.Node,)
        filterset_class = PurchaseOrderFilter

    @staticmethod
    def resolve_products(self, info, **kwargs):
        return PurchaseOrderProduct.objects.filter(order_id=self.id).order_by('product_name').all()

Теперь ваш запрос будет выглядеть так:

query {
    purchases(first: 15, after: "", products_ProductName: "access") {
        edges {
            node {
                products {
                    edges {
                        node {
                            productName
                        }
                    }
                }
            }
        }
    }
}

И ответ:

{
    "data": {
        "purchases": {
            "edges": [
                {
                    "node": {"products": {"edges": [{"node": {"productName": "access1"}}]}}
                }
            ]
        }
    }
}
Вернуться на верх