On 06/12/06, Matthew Bevan <[EMAIL PROTECTED]> wrote:
>
> > Hmmm, this is normal because the same controller method showing the
> > form is also validating it (with the decorator), therefore when
> > called with no request params required fields fail validation and the
> > form thinks it's being redisplayed so it prints errors and input
> > values (all blank).
> > I can think of three ways to circumventing it:
>
> I wrote and submitted to the docs.turbogears.org server the following:
>
> http://docs.turbogears.org/1.0/UnifiedControllers
>
> It describes in full detail (with source code) how to combine form/
> action controllers without any of problems associated with just
> @exposing and @validating the entire thing. The code described also
> has the added benefit of allowing validation of forms built at
> execution time.
>
> The gist of it is:
>
> class MyController(Controller):
> @expose(template="project.templates.genericform")
> def index(self, **kw):
> form = MyForm(fields=MyFields())
>
> if kw:
> @validate(form=form)
> def get_errors(self, tg_errors=None, **data):
> return tg_errors, data
>
> tg_errors, data = get_errors(self, **kw)
>
> if not tg_errors:
> # Perform some action with the data in **data.
> # **kw still contains the raw data.
> pass
>
> turbogears.flash("Some success message.")
> turbogears.redirect("/")
>
> else:
> turbogears.flash("Some error message.")
>
> else:
> # Supply some default data, if required.
> # Optionally supplying data allows you to combine
> # create and modify actions in one.
> data = dict(...)
>
> return dict(title="Foo Bar", form=form, data=stock_data)
>
> Top Floor has been using this structure extensively without
> problems. Enjoy!
I really like this. It's a good idea, and neatly done.
The one enhancement I'd like to make, and have been struggling to with
myself, is to turn it into a generic controller.
For me, I have to produce lots of forms, but there's few variables
between them (form, table, welcome message, thanbk you message, etc).
Most of which would work fine except that the validate decorator
complains if the form doesn't exist at the point when the function is
decorated. So I moved it into __init__:
class FormController(controllers.Controller):
def __init__(self, form, table, page, intro_text="",
thank_you="Thank you."):
super(FormController, self).__init__()
self.form = form
self.table = table
self.page = page
self.intro_text = intro_text
self.thank_you = thank_you
@expose()
@validate(form=self.form)
@error_handler(self.index)
def save(**kwargs):
table.save(**kwargs)
raise redirect('thank_you')
self.save = save
@expose(template='.templates.form')
def index(self):
page = self.page
form = self.form
intro_text = self.intro_text
return dict(page=page, form=form,
intro_text=intro_text)
@expose(template='.templates.form_thankyou')
def thank_you(self):
page = self.page
thank_you = self.thank_you
return dict(page=page, thank_you=
thank_you)
It doesn't yet work, as when you save the form you get the error:
Page handler: <function save at 0x2262030>
Traceback (most recent call last):
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 105, in _run
self.main()
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 254, in main
body = page_handler(*virtual_path, **self.params)
File "<string>", line 3, in save
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/TurboGears-1.0b1-py2.4.egg/turbogears/controllers.py",
line 326, in expose
output = database.run_with_transaction(
File "<string>", line 5, in run_with_transaction
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/TurboGears-1.0b1-py2.4.egg/turbogears/database.py",
line 246, in so_rwt
retval = func(*args, **kw)
File "<string>", line 5, in _expose
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/TurboGears-1.0b1-py2.4.egg/turbogears/controllers.py",
line 343, in <lambda>
mapping, fragment, args, kw)))
File
"/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/TurboGears-1.0b1-py2.4.egg/turbogears/controllers.py",
line 367, in _execute_func
output = errorhandling.try_call(func, *args, **kw)
TypeError: try_call() takes at least 2 non-keyword arguments (1 given)
I'm wondering if this might be easier to do with your method of having
a single function that does everything. But I'm not too
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---