CRUDRestController and REST urls

41 views
Skip to first unread message

ozwyzard

unread,
Apr 5, 2010, 8:20:29 PM4/5/10
to TurboGears
When using CRUDRestController, is there a way to implement REST style
URLs as follows?
http://website.com/controller_1/arg_11/arg_12/controller_2/arg_21/arg_22

It seems the CRUDRestController is not derived from
ObjectDispatchController, so the new TG2 'lookup' method does not
apply. As a workaround, I am trying to implement the above by
instantiating controller2 within controller1's get_one() method.

References:
http://turbogears.org/2.0/docs/modules/tgcontroller.html#tg.controllers.DecoratedController
http://turbogears2.sourcearchive.com/documentation/2.0.1/controllers_8py-source.html


Thanks.

Wesley Dyk

unread,
Apr 6, 2010, 11:21:55 PM4/6/10
to turbo...@googlegroups.com
> --
> You received this message because you are subscribed to the Google Groups "TurboGears" group.
> To post to this group, send email to turbo...@googlegroups.com.
> To unsubscribe from this group, send email to turbogears+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/turbogears?hl=en.
>
>

I would check out this link on the RestController implementation of
the same style. The key is the __before__ method. CrudRestController
implements this method, so be sure to call it if you override it.

http://turbogears.org/2.0/docs/main/RestControllers.html#nesting-resources-with-restcontrollers

Wes

ozwyzard

unread,
Apr 7, 2010, 10:42:52 PM4/7/10
to TurboGears
Thanks. I had toyed with __before__ but I will dig further.

On Apr 6, 8:21 pm, Wesley Dyk <aus...@gmail.com> wrote:


> On Mon, Apr 5, 2010 at 6:20 PM, ozwyzard <ozwyz...@gmail.com> wrote:
> > When using CRUDRestController, is there a way to implement REST style
> > URLs as follows?
> >    http://website.com/controller_1/arg_11/arg_12/controller_2/arg_21/arg_22
>
> > It seems the CRUDRestController is not derived from
> > ObjectDispatchController, so the new TG2 'lookup' method does not
> > apply.  As a workaround, I am trying to implement the above by
> > instantiating controller2  within controller1's get_one() method.
>
> > References:

> >http://turbogears.org/2.0/docs/modules/tgcontroller.html#tg.controlle...
> >http://turbogears2.sourcearchive.com/documentation/2.0.1/controllers_...


>
> > Thanks.
>
> > --
> > You received this message because you are subscribed to the Google Groups "TurboGears" group.
> > To post to this group, send email to turbo...@googlegroups.com.
> > To unsubscribe from this group, send email to turbogears+...@googlegroups.com.

> > For more options, visit this group athttp://groups.google.com/group/turbogears?hl=en.


>
> I would check out this link on the RestController implementation of
> the same style.  The key is the __before__ method.  CrudRestController
> implements this method, so be sure to call it if you override it.
>

> http://turbogears.org/2.0/docs/main/RestControllers.html#nesting-reso...
>
> Wes

ozwyzard

unread,
Apr 26, 2010, 11:25:07 PM4/26/10
to TurboGears
Thanks. I was trying the __before__ method in the parent controller
as opposed to the leaf controller. Once I overrode the __before__
method in the leaf (child) controller, I was able to get the nesting
working for get and get_all. However, edit and delete fail in genshi
when trying to iterate through menu_items (even though I am not using
menu_items). I have posted a separate post to ask where I can find
the source code for CrudRestController.

Module ?:19 in <Expression
u'iter(sorted(tmpl_context.menu_items.iteritems()))'>
<< <div style="float:left; padding-left:0px;">
<ul id="menu_items" py:if="hasattr(tmpl_context,
'menu_items')">
<li py:for="lower, item in
sorted(tmpl_context.menu_items.iteritems())">
<a href="${'../' * (1 + value_of('pk_count', 1))}$
{lower}s/">$item.__name__</a>
</li>
>> <li py:for="lower, item in sorted(tmpl_context.menu_items.iteritems())">
Module genshi.template.eval:321 in lookup_attr view
Module genshi.template.eval:405 in undefined view
UndefinedError: '' has no member named "iteritems"


==================

On Apr 6, 11:21 pm, Wesley Dyk <aus...@gmail.com> wrote:
> On Mon, Apr 5, 2010 at 6:20 PM, ozwyzard <ozwyz...@gmail.com> wrote:
> > When using CRUDRestController, is there a way to implement REST style
> > URLs as follows?
> >    http://website.com/controller_1/arg_11/arg_12/controller_2/arg_21/arg_22
>
> > It seems the CRUDRestController is not derived from
> > ObjectDispatchController, so the new TG2 'lookup' method does not
> > apply.  As a workaround, I am trying to implement the above by
> > instantiating controller2  within controller1's get_one() method.
>
> > References:
> >http://turbogears.org/2.0/docs/modules/tgcontroller.html#tg.controlle...
> >http://turbogears2.sourcearchive.com/documentation/2.0.1/controllers_...
>
> > Thanks.
>
> > --
> > You received this message because you are subscribed to the Google Groups "TurboGears" group.
> > To post to this group, send email to turbo...@googlegroups.com.
> > To unsubscribe from this group, send email to turbogears+...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/turbogears?hl=en.
>
> I would check out this link on the RestController implementation of
> the same style.  The key is the __before__ method.  CrudRestController
> implements this method, so be sure to call it if you override it.
>
> http://turbogears.org/2.0/docs/main/RestControllers.html#nesting-reso...
>
> Wes

ozwyzard

unread,
Apr 27, 2010, 8:46:08 PM4/27/10
to TurboGears
IS THERE ANY WAY TO CONSUME THE ARGUMENTS IN __before__ OR VIA SOME
OTHER OVERRIDE?

Sample nested URL: .../CONTROL1/arg1/CONTROL2/arg2

In the overridden __before__ routine, I added the lines that the
default __before__ in CrudRestController does:

def __before__(self, *args, *kw):
tmpl_context.menu_items = self.menu_items
tmpl_context.title = self.title
... split the url ...
self.parent_arg = arg1


With the above changes, the menu_items is None and avoids the
exception in the template rendering.

However, the post_delete() function in CrudRestController still gets
all the original arguments and tries to delete the wrong record, since
the *args passed to __before__ is a tuple and cannot be consumed by
__before__ and the underlying model (for CONTROL2) has just 1 primary
key v.i.z. arg2. I.E. pks = [id] but args = (arg1, CONTROL2, arg2)
and it tries to use arg1 as the primary key to CONTROL2 and fails.

@expose() #CrudRestController source code
def post_delete(self, *args, **kw):
"""This is the code that actually deletes the record"""
pks = self.provider.get_primary_fields(self.model)
d = {}
for i, arg in enumerate(args):
d[pks[i]] = arg
self.provider.delete(self.model, d)
redirect('./' + '../' * (len(pks) - 1))


IS THERE ANY WAY TO CONSUME THE ARGUMENTS IN __before__ OR VIA SOME
OTHER OVERRIDE?

Thanks.

ozwyzard

unread,
Apr 27, 2010, 8:49:18 PM4/27/10
to TurboGears
In summary, post_delete would work if it attempted a delete using arg2
as the primary key (for CONTROL2) as opposed to using arg1 (which is
CONTROL1's primary key).

Thanks.

ozwyzard

unread,
Apr 27, 2010, 9:28:44 PM4/27/10
to TurboGears
Sorry for the many posts. Looks like the post_delete operation on
CONTROL2 is attempting to the parent controller CONTROL1. The URL is
correct (verified using extra-data on debugger and via network sniffer
wireshark). It uses the correct controller for get_one and get_all,
but the wrong (parent) controller for post_delete (have not confirmed
edit operation yet). Thanks.

Sample nested URL: .../CONTROL1/arg1/CONTROL2/arg2
Reply all
Reply to author
Forward
0 new messages