Запуск другой базы запросов на родительском ресурсе

#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 . СМ