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"}}]}}
}
]
}
}
}