[Grok-dev] Re: REST branch ready for review
Martijn Faassen
faassen at startifact.com
Sun Oct 21 18:17:25 EDT 2007
Jan-Wijbrand Kolman wrote:
> Martijn Faassen wrote:
>> To actually issue REST requests over a URL, you need to define a REST
>> protocol that uses this layer:
>
> After reading and trying it is not clear to me what the relationship is
> between the "layer" and the "protocol" components. Can you elaborate on
> this?
My apologies taking a while getting back to you. Thank you for your review!
The terminology is perhaps not ideal, but it actually mimics 'layer' and
'skin'.
In Grok, views can be layers, indicated by grok.layer(). A layer is just
an interface that derives from a particular layer. Since you can use
inheritance (including multiple inheritance), you can combine multiple
layers into a single one this way.
A skin turns a layer into something that is available on a url, giving
it a name, like ++skin++foo. It might also add other information
eventually, like a title and a description, that could aid a UI.
For REST, I've retained the concept of layer, but made a base layer for
REST instead. I've introduce something very skin-like which is a REST
protocol, and that appears like this in a URL: ++rest++foo.
This way, you could compose a single REST protocols out of multiple
protocols should you so desire. Might not be very common (it's hard to
tell), but since all concepts from layers and skins are reused, it
shouldn't be hard to learn once you know the former. It's also not a lot
of overhead to just work with a single layer (or even use the default
REST layer).
> For example, I played around with this code:
>
> import grok
>
> class TestRest(grok.Application, grok.Container):
> pass
>
> class Index(grok.View):
> pass # see app_templates/index.pt
>
> class FirstLayer(grok.IRESTLayer):
> pass
>
> class SecondLayer2(grok.IRESTLayer):
> pass
>
> class FirstREST(grok.REST):
> grok.context(TestRest)
>
> def GET(self):
> return 'GET' + repr(self)
>
> class SecondREST(grok.REST):
> grok.context(TestRest)
>
> def GET(self):
> return 'SECOND GET' + repr(self)
>
> class FirstProtocol(grok.RESTProtocol):
> grok.layer(FirstLayer)
> grok.name('foobar')
>
> And now if I go to
>
> http://localhost:8080/++rest++foobar/mytestrestinstance
>
> I get:
>
> SECOND GET<grok.meta.SecondREST object at ...>
>
> Why do I get to the "SecondREST" view here?
This is indeed surprising. It's because if you *don't* assign a
grok.REST class to a particular layer, it'll use the IRESTLayer by
default. This means that *all* REST skins will share this.
I wonder whether this is really analogous to the behavior of skins and
layers? Does anyone know off the top of their head what happens if you
don't put a grok.View subclass into a particular layer? Does it then
exist in all skins?
We could decide to make the default REST layer be a very particular
layer instead that never shows up automatically... Alternatively it
could simply complain if no layer is found. What do people think? (also
for skins).
> And shouldn't Grok complain about the fact that I have created two
> layers, but I do not have explicit use a grok.layer() directive in my
> grok.REST subclasses?
There is nothing going on like automatic context association for layers.
Should there be? The situation is somewhat different from context, as
layers are almost always reused across modules. It is possible to use
the grok.layer() directive on a module-level basis to provide a
module-level default.
Regards,
Martijn
More information about the Grok-dev
mailing list