#pyramid #traversal
#пирамида #обход
Вопрос:
Я работаю над проектом обхода пирамиды, и я хочу запустить другой запрос для получения той же базы ресурсов для ее родительского ресурса или около того.
Допустим, у меня есть 3 ресурса: клиент, магазин, заказ. теперь и у клиента, и у магазина может быть список заказов. Итак, я определяю OrderListResource как ресурс, и мое мнение похоже:
@view_config(context=resources.OrderListResource, renderer='json')
def view_order_list(context, request):
return {orders: context.retrieve_method()}
Теперь мне интересно, как лучше всего получить базу данных на родительском ресурсе?
Например, как OrderListResource должен решить получать заказы по идентификатору клиента или по идентификатору магазина. логика должна лежать в представлении или в самом ресурсе?
Спасибо.
Ответ №1:
Ну, поскольку вы используете обход, добраться до родительского ресурса очень просто:
parent = context.__parent__
query = session.query(OrderList)
if isinstance(parent, CustomerResource):
query = query.filter(OrderList.customer_id == parent.id)
elif isinstance(parent, StoreResource):
query = query.filter(OrderList.store_id == parent.id)
Если родительский элемент, который вы хотите проверить, может не быть непосредственным родительским элементом вашего ресурса, вы можете использовать метод pyramid.traversal.find_interface.
В качестве альтернативы, если логика сильно отличается в зависимости от того, содержится ли заказ в клиенте или магазине, у вас может быть два отдельных представления с использованием предиката containment
view .
@view_config(context=resources.OrderListResource, containment=CustomerResource, renderer='json')
def view_order_list_for_customer(context, request):
return ...
@view_config(context=resources.OrderListResource, containment=StoreResource, renderer='json')
def view_order_list_for_store(context, request):
return ...
Комментарии:
1. Я никогда не имел ни малейшего представления о сдерживании . я проверю это. Спасибо.
Ответ №2:
Учитывая, что каждый ресурс в дереве ресурсов имеет идентификатор, тогда какова цель и идентификатор вызываемого ресурса OrderListResource
? Чтобы сопоставить ресурс как контекст во время обхода, он должен быть создан ранее. Вы хотите обновить эти ресурсы, выполняя операции CRUD с вашими реальными ресурсами??? Вот почему я понимаю вашу идею OrderListResource
как сбор ресурсов заказа в результате динамического запроса во время выполнения приложения.
Вы хотите хранить клиентов, магазины и заказы. У каждого клиента, магазина и заказа есть идентификатор, который позволяет вам находить товар в коллекции. Вы могли бы создать такое дерево ресурсов.
root (/) (Root Resource)
|- customers (Container supporting traversal)
|- stores (Container supporting traversal)
|- orders (Container supporting traversal)
Шаблоны URL для обхода дерева ресурсов
/customers/{uid}
/stores/{uid}
/orders/{uid}
Учитывая, что вы сохраняете связь с store
customer
ресурсом и order
в нем, как запросить связь между вашими ресурсами с помощью естественного шаблона URL, который хорошо вписывается в существующие шаблоны URL?
/customers/{uid}/orders
/stores/{uid}/orders
Поиск заказов от одного клиента
@view_config(name='orders', context=resources.Customer, renderer='json')
def view_order_list_for_customer(context, request):
customer = context.__name__
orders = request.root['orders']
orders_by_customer = [order for order in orders if order.customer == customer]
return dict(orders = orders_by_customer)
Поиск заказов из одного магазина
@view_config(name='orders', context=resources.Store, renderer='json')
def view_order_list_for_store(context, request):
store = context.__name__
orders = request.root['orders']
orders_by_store = [order for order in orders if order.store == store]
return dict(orders = orders_by_store)
Эти представления зависят от местоположения и позволяют создавать запрос с информацией из заданного контекста.
Пожалуйста, обратите внимание, что имя представления совпадает с именем ресурса, содержащего все Order
ресурсы.
Для изучения взаимосвязи между двумя ресурсами ваши URL-адреса обычно будут выглядеть следующим образом
/resource/identifier/resource
Комментарии:
1. Да, я совершенно забыл о имени представления. но имя вида afaik должно быть последней частью URL, верно? если да, то как могут работать customers/{uid}/orders/{uid} ?
2. Я не понимаю цели этого URL. пожалуйста, объясните. Запомните подробности о ‘context’, ‘view name’ и ‘subpath’ — docs.pylonsproject.org/projects/pyramid/en/latest/narr /…
3. ОК. я путал ваш путь с моим! в любом случае проблема в том, что у меня уже есть ключ «заказы» в ресурсах моего клиента и магазина. так что имя представления не могло сильно помочь. я думаю, что более логично использовать ключевое слово containment в определении представления или просто проверить, является ли type(context.parent) == customer … . В любом случае спасибо за ваш ответ.
4. Эта информация определенно должна была быть частью вашего вопроса. Ключ ‘orders’ предназначен для изучения взаимосвязи в коде модели, но вы просили изучить его в коде представления. Может быть, мне следовало запросить больше контекста и деталей. В любом случае я не вижу никакой ценности в создании OrderListResource, и поскольку Order связан с Customer И Store, нет четких отношений родитель / потомок. Я хотел бы услышать от вас еще один вопрос о SO, обсуждающий вашу модель домена.
5. Почему OrderListResource? ну, существует отношение «один ко многим» от клиента к заказу и от магазина к заказу, поэтому в CustomerResource getitem , если ключ равен ‘orders’, OrderListResource будет возвращен без выполнения какого-либо запроса к БД. потому что я не хочу заполнять все заказы до того, как они мне действительно понадобятся. например, этот URL:/customers/c_id/orders/o_id я просто хочу получить один конкретный заказ (o_id). итак, в getitem OrderListResource запрос будет выполнен, и он вернет указанный OrderResource . СМ