Traject integration for Grok applications
Include megrok.traject by adding it in your Grok project’s setup.py (in install_requires) and re-run buildout.
External trajects are most useful if you do not directly control the models. This may for instance be the case if the models are defined in an external package.
With megrok.traject you can declare trajects in Grok like this:
from megrok import traject class SomeTraject(traject.Traject): grok.context(App) pattern = 'departments/:department_id' model = Department def factory(department_id): return get_department(department_id) def arguments(department): return dict(department_id=department.id)
This registers factory and the inverse arguments functions for the pattern departments/:department_id, the root App and the class Department. This replaces the register* functions in traject itself.
App is any grok model. This model now automatically allows traversal into the associated patterns; the system registers a custom traverser to do this.
You can register grok views for Department as usual.
If you can, make the models exposed by traject subclass from grokcore.component.Context (or its alias grok.Context, or its alias traject.Context). By doing so, you avoid the problems described below.
Sometimes you cannot subclass your models from grokcore.component.Context, however. Exposing external models was something that megrok.traject was designed to allow, after all.
When you use megrok.traject with external models, you can run into the following two issues with your models:
The ZTK assumes the default view for objects is index.html, not index. The index default view setting is only used when you subclass your model from grokcore.component.Context. You can still make index the default view of your model by adding the following directive to your project’s configure.zcml:
<browser:defaultView for="SomeForeignModel" name="index" />
You can also do this for a common base class that you know all your models share, or a common interface that you know is provided by all your models.
Views, adapters and such won’t auto-associate with your models in the same module. You will need to explicitly use the grok.context() on the module or class level to associate your component. For example:
class SomeForeignModel(object): ... class MyView(grok.View): grok.context(SomeForeignModel)
If you have control over the model definitions yourself, traject allows a more compact notation that lets you define traject-based models directly:
import traject class Department(traject.Model): traject.context(App) traject.pattern('departments/:department_id') def factory(department_id): return get_department(department_id) def arguments(self): return dict(department_id=self.id)
traject.Model derives from grokcore.component.Context, so the issues mentioned above with external models won’t be a problem here.
Note that Traject models are not persistent in the ZODB sense. If you need a persistent Traject models you can mix in grok.Model or persistent.Persistent.
- return None in factory if the model cannot be found. The system then falls back to normal traversal to look up the view. Being too aggressive in consuming any arguments will break view traversal.
- Use megrok.traject.locate to locate an object before asking for its URL or doing checkPermission on it. If the object was routed to using megrok.traject already this isn’t necessary. This is a simple import alias for traject.locate.
- Instead of normal methods (which get interpreted as functions) for factory and arguments, you can also turn them into class methods using the @classmethod decorator. They now take a cls argument as the first argument which is the class they are defined on. This can be useful if you want to make the implementations of these functions depend on information on its class (such as the value of model), and this in turn can be useful to implement more declarative traject base classes.
For more information see the traject documentation.
- Can now also use @classmethod for factory and arguments. This is useful if these functions depend on information on the class they are defined on.
- Added notes to documentation about deriving your models from grokcore.component.Context, or what to do what you can’t.
- Expose traject.Context for convenience reasons.
- Fixed ReST documentation.
- Support traject.Model, a more compact way to define trajects if the model is under the control of the developer.
- Initial public release.