Browse files

Document new inherit option of @expose with examples

  • Loading branch information...
1 parent b192580 commit 73d72d0185de4b2665c42a8e925b2a54a6cf3e36 @amol- amol- committed Jun 7, 2012
Showing with 60 additions and 7 deletions.
  1. +7 −7 docs/main/Extensions/Crud/index.rst
  2. +53 −0 docs/main/TGControllers.rst
14 docs/main/Extensions/Crud/index.rst
@@ -117,7 +117,6 @@ argument.
In the previous example calling http://localhost:8080/tickets/5/done will set the
ticket 5 status to done.
Creating our own CrudRestController
@@ -366,18 +365,19 @@ Here is what your new controller code would look like::
# (...)
- @expose()
+ @expose(inherit=True)
def post(self, **kw):
return super(MovieController, self).post(**kw)
You might notice that the function has the @expose decorator. This is
required because the expose decoration occurs at the class-level, so
that means that when you override the class method, the expose is
-eliminated. We add it back to the method by adding @expose. To
-change the functionality of a "GET" method, you would add
-@expose('genshi:tgext.crud.templates.get_all') if you desired to use
-the existing exposed template.
+eliminated. We add it back to the method by adding @expose with the
+``inherit`` parameter to inherit the behavior from the parent method.
+For more details you can refer to the
+:ref:`TGController Subclassing <tgcontrollers-subclassing>` documentation.
Overriding Templates
@@ -390,7 +390,7 @@ simply returning the value of the super class's method.::
# (...)
- @expose(movie_demo.templetes.my_get_all_template)
+ @expose('movie_demo.templates.my_get_all_template', inherit=True)
def get_all(self, *args, **kw):
return super(MovieController, self).get_all(*args, **kw)
53 docs/main/TGControllers.rst
@@ -84,6 +84,59 @@ you to use actual objects with data in your controllers.
Plus, it makes RESTful URLs much easier than they were in TurboGears 1.
+.. _tgcontrollers-subclassing:
+Subclassing Controllers
+When overriding a parent controller method you will usually have to expose it
+again and place any validation or event hook it previously had.
+While this is possible, it is not the best way to add additional behavior to
+existing controllers. If they are implemented in an external
+library or application, you will have to look at the code of the library,
+see any template it exposed, any hook it registered and place them again.
+If the library will change in any future release your code will probably
+stop working.
+To avoid this behavior and the issues it raises since TurboGears 2.2
+it is possible to subclass controllers inheriting the configuration
+the parent methods had.
+The ``inherit`` parameter of the :py:class:`tg.decorators.expose` decorator
+enables this behavior::
+ class OriginalController(TGController):
+ @expose('mylib.templates.index')
+ def index(self):
+ return dict()
+ @expose('mylib.templates.about')
+ def about(self):
+ return dict()
+ @expose('json')
+ def data(self):
+ return {'v':5}
+ class MyCustomizedController(OriginalController):
+ @expose(inherit=True)
+ def index(self, *args, **kw):
+ dosomething()
+ return super(MyCustomizedController, self).index(*args, **kw)
+ @expose('myapp.templates.newabout', inherit=True)
+ def about(self):
+ return super(MyCustomizedController, self).about(*args, **kw)
+ def _before_render_data(remainder, params, output):
+ output['child_value'] = 'CHILDVALUE'
+ @expose(inherit=True)
+ @before_render(_before_render_data)
+ def data(self, *args, **kw):
+ return super(MyCustomizedController, self).data(*args, **kw)
Mount Points and Dispatch

0 comments on commit 73d72d0

Please sign in to comment.