I'm trying to change the options of a SingleSelectField used in a
RepeatingFormField ...
class AddPrest(widgets.WidgetsList):
ope = widgets.SingleSelectField(name='operat',options=[],
validator=Int(strip=True))
class AddFields(widgets.WidgetsList):
casl =
widgets.SingleSelectField(name='casl',options=opt_cli,validator=UnicodeString(not_empty=True,
strip=True),
attrs=dict(onchange='form.submit()'))
prest =
RepeatingFormField(name='prest',fields=AddPrest(),repetitions=10)
addForm = TableForm(fields=AddFields(), action='save_many')
when I try to change value options as:
addForm.fields[0].fields[0].options = my_list
I have this error:
*exceptions.ValueError: ('It is not threadsafe to modify widgets in a
request')
is there a way to do that?
thank you,
jo
*
could you give more details?
> thank you,
> jo
>
> *
>
> >
>
Actually this is a good question that I have a problem with myself all
of a sudden.
What if the options for select fields is dynamically obtained for each
invocation of the form?
My other question that has just bitten me on this is the format
parameter for a DatePicker widget. At the moment I specify it in the
form which, as normal, gets constructed at load time. However, I need to
set the date format dynamically according to the language of the current
request.
Can these things be done dynamically for widgets in forms? Can it be
done in the controller or template? Seems pretty fundamental. Most
likely I have missed something obvious as usual....
Thanks,
Gary.
I'm still trying to figure out how to do this the best way too. What I
want to have a happen is for the field callable class ( the one with the
fields, subclassing widget list ) to receive a runtime object used to
get the defaults. But as the fields are static members and not instance
fields, I'm still not clear what the right way to do this is.
If anyone can point me at an example of this it would be much
appreciated.
Thanks
iain
There are two options:
- pass a callable to options. It will be evaluated each time the form
is rendered.
- pass the options as parameter to the form when rendering it:
${form.display(value, options={'fieldname' : <optionlist/>})}
See this:
http://groups.google.co.kr/group/turbogears/browse_thread/thread/15f0585b4604405b
> My other question that has just bitten me on this is the format
> parameter for a DatePicker widget. At the moment I specify it in the
> form which, as normal, gets constructed at load time. However, I need to
> set the date format dynamically according to the language of the current
> request.
This is actually a lack in the DateTimeConverter.
I personally have a patched version that allows format to be passed a
callable to allow what you want.
If I come to it, I'll send it to you tomorrow, as the code is at work.
Diez
This one's easy to answer.
The only question you should as is:
Are my <field> options dependent on some previous choice made on the same
form? (e.g. countries -> states, states -> cities)
NO
Use a callable to populate the field
YES
Use AJAX to populate the field.
You'll always have a method that will return the options based on some filter
(possibly with default values) and that can be exposed through JSON or not.
For the example above:
@expose('json') # Just if using AJAX...
def my_states(self, country=None):
return self._my_states(country)
# This version can be used inside the application, without the JSON armor
def _my_states(self, country=None):
states = model.State.select()
if country is not None:
states = states.filter(model.State.q.country = country)
return dict(states = states)
my_widget = widgets.SomeWidget(
...
options = self._my_states(default_country)
...
)
The AJAX code depends on your widget, your other fields, etc. You'll find
lots of examples on the archives and googling for them.
--
Jorge Godoy <jgo...@gmail.com>
With a little more digging I had just got this one sorted. Thanks.
>> My other question that has just bitten me on this is the format
>> parameter for a DatePicker widget. At the moment I specify it in the
>> form which, as normal, gets constructed at load time. However, I need to
>> set the date format dynamically according to the language of the current
>> request.
>
> This is actually a lack in the DateTimeConverter.
>
> I personally have a patched version that allows format to be passed a
> callable to allow what you want.
>
> If I come to it, I'll send it to you tomorrow, as the code is at work.
>
> Diez
Sadly I need to change the format in the FormEncode schema that goes
with the form as well. I know that TG's own DateTimeConverter will
assume a validator of the same format as the widget, but on a couple of
forms I need to specify a DateTimeConverter validator in conjunction
with others on that field. I guess I will eventually work around that as
well.
I think the main problem is that there seems to be no easy and efficient
way to generate and use a form/widgetlist/validator modifiable
*instance* at runtime. The above two problems were just the first I've
come across with this static construction model for forms. I'm sure
there will be others.....
Most other frameworks I've used (Django, .NET, ...) construct a "form"
instance at runtime per request. You then fiddle with this as desired
for this specific request and get it displayed.
Thanks again,
Gary.
I'd have to agree with that! It seems a lot more complicated to deal
with the statics, and would be much easier to extend me thinks. Does
ToscaWidgets address this at all?
Arg, I feel like the widgets are so close to being amazing but that left
over 10% is rough going.
Iain
OK, that's great. I've tested that with statically declared forms and it
seems to work OK. Just the DatePicker's date format to get around then :)
One more question if I may. How to change the attributes of statically
declared form fields at runtime. I need to set some fields to readonly
or change the maxlength of a TextField for example. What's the best way
to do this per request?
Thanks for your help,
Gary.
> One more question if I may. How to change the attributes of statically
> declared form fields at runtime. I need to set some fields to readonly
> or change the maxlength of a TextField for example. What's the best way
> to do this per request?
Hmmm... You can't change some things after you instantiated your widget. The
best way that I know that would work is using AJAX to get the values from the
application and then changing the aspect of the form with your callback.
But depending on what you want to change it might be possible by passing a
dict to your widget on your view.
--
Jorge Godoy <jgo...@gmail.com>
I think that the widgets are definitely the way to go. It's the "big
picture" that seems to be problematic. I'm not sure that ToscaWidgets
fixes any of this, but I've only had a quick play with them.
I think the other problem is the multi-threading stuff. In my 20 years
doing software I've come across people who just cannot get it, no matter
how much you explain it. Sometimes I have to just step back and re-think
what is going on in a multi-thread environment and then sort the code
out appropriately.
In the web environment you've got this dynamic "every request is
different" approach, yet with this type of framework/application you
always seem to be thinking so hard about concurrent re-use of a pool of
static resources. Sometimes it just makes my head hurt :)
I'm sure we will get there.....
Regards,
Gary.
> I think that the widgets are definitely the way to go. It's the "big
> picture" that seems to be problematic. I'm not sure that ToscaWidgets
> fixes any of this, but I've only had a quick play with them.
Anyway, you have to remember that you don't need to be limited by the default
widget template or even the default parameters that a widget accepts.
Subclassing a widget and creating your own is really easy!
Take a look at the code for the Select Shuttle for a somewhat complex widget
(I have some that are much more complex, such as one that has 49 input fields
for time inputs -- 42 of them -- and boolean values -- the other 7).
For a simple widget take a look at Submodal.
Those are "100%" custom widgets. But you can also subclass a widget just to
change its template -- it might be worth if you're using this alternative
template in several places to avoid having to specify the new template every
time -- or even add new parameters. Wanna see an example?
class MyPaginate(widgets.PaginateDataGrid):
template = 'my_app.templates.my_paginate_template'
params = ['extra1', 'extra2']
Then I can pass values for "extra1" and "extra2" when I call my instance of
MyPaginate (or when I subclass it).
Those can be used to render the widget differently on a per request basis as
you're both wanting.
> I think the other problem is the multi-threading stuff. In my 20 years
> doing software I've come across people who just cannot get it, no matter
> how much you explain it. Sometimes I have to just step back and re-think
> what is going on in a multi-thread environment and then sort the code
> out appropriately.
Add to that another problem: the web is *stateless*. There's nothing that
says that when you submit a form you'll get the same thread / process that
generated it.
> In the web environment you've got this dynamic "every request is
> different" approach, yet with this type of framework/application you
> always seem to be thinking so hard about concurrent re-use of a pool of
> static resources. Sometimes it just makes my head hurt :)
It is hard until you get it in your veins. ;-) After that you get used to it
and it is simple to work with.
> I'm sure we will get there.....
I have no doubt.
--
Jorge Godoy <jgo...@gmail.com>
Ah, I just feel like I'm digging myself a big hole here.
It just seems really messy to have to resort to AJAX and add stuff into
both controller and view just to toggle some properties on some fields
at runtime. From the nature of MVC this really ought to be done in the
controller as it may require complex logic to sort it out.
I can't believe that this is not often needed for most real world
applications. What do other people do in this situation?
I'll look into what I can do by passing dicts to the template.
In .NET I would have done something like this:
if (user.viewolnly)
{
field1.readonly = true;
....
field10.readonly = true;
field11.maxlength = 32;
}
In that system, each valid HTML attribute is exposed as a property on a
"widget". This makes it so simple to program. This would still not work
for TG though because of the single instance nature of forms (at least
in the standard, recommended way of doing things)
It would be very nice if something similar were available in TG or at
least in ToscaWidgets before TG 2.0 is done.
Thanks again,
Gary.
I agree and I've done that already for a couple of widgets
(CheckboxList) to get different behaviour. However, I think I'll end up
subclassing the whole widgets system before I'm finished.
> .....
> Those are "100%" custom widgets. But you can also subclass a widget just to
> change its template -- it might be worth if you're using this alternative
> template in several places to avoid having to specify the new template every
> time -- or even add new parameters. Wanna see an example?
>
Again, I understand this and I have already subclassed a couple of
widgets to change the template etc. I've even created a CSSForm derived
from Form to layout a form using CSS rather than Table or List Forms.
What I'm really talking about though is not creating new widgets with
different behaviour, but getting standard behaviour into even the
simplest widgets to just manipulate their properties at runtime.
I see two options for myself at the moment:
Subclass all the widgets I want to use and change the underlying code to
enable changeing lots of things at runtime. This seems a potentially
large sub-project though that I don't really want to tackle right now.
Change my controllers to create a list of widgets at runtime and set
properties etc. that way. This will certainly work and it very clean,
but is a runtime performance hit because of re-creating the widgets for
every request.
In my design, this web application will end up with around 80 different
forms (hopefully quite a few re-usable generic templates :) ) but I
guess I need to determine my strategy now.
Thanks for all your input,
Gary.
> I can't believe that this is not often needed for most real world
> applications. What do other people do in this situation?
Custom widgets?
> It would be very nice if something similar were available in TG or at
> least in ToscaWidgets before TG 2.0 is done.
You can achieve that with a custom widget today.
--
Jorge Godoy <jgo...@gmail.com>
Oh, OK, it looks like I will have to create custom widgets for pretty
much all of them then. I think I'll have a look at the whole widgets
framework and try to find the best place to put this functionality in
generically.
Thanks for the advice..
BTW I just had a peek at the Django newforms widgets (fields). It
seems they had a similar problem. It looks like it was solved by
creating the form definition statically (like TG) but at runtime the
user creates an instance of the form. At instance construction the
form copies its class field attributes into instance fields attributes
(self.fields) so that they can be modified at runtime without
affecting any other form instance. This seems to work for statically
declaring the form but is efficient and flexible at runtime as the
form "definition" (the list of widgets etc.) is copied to a mutable
instance.
The TG widgets are somewhat more complex than the Django ones, but I
might take a look at this.
Thanks,
Gary.
Are you talking about this kind of functionality?
In controller:
form = w.TableForm(fields = [w.TextField('userName')])
In template:
${form(attrs=dict(userName=dict(maxlength='12')))}
The attribute readonly might work but i'm not really familiar with
valueless attributes(selected, checked, readonly). I think readonly
is kind of new to non-ms browsers as well. I really never understand
why you would use it either.
PS: By passing the data to the form at display time we can use the
static form and fields over and over without wasting memory and the
processing power to recompile the template repeatedly.
-Ian
Not really.
More like:
Declare the form statically as per now.
class MyFields(widgets.WidgetsList):
description = widgets.TextField(label="Description")
class MyForm():
fields = MyFields()
in the page handler:
form = MyForm()
if user.is_restricted:
form['description'].update_attrs({'readonly':'readonly'})
form['description'].label = "A different label"
.....
I.e. I would like to "create" a form instance, modify a few bits
(perhaps) then send it to the template for display together with the
values as per now.
Most, if not all of this should really be done in the controller
without putting to much extra logic in the template. This way, you
still only need ${form.display(value=myvalues)} in the template....
With the current widgets implementation this is not possible except by
creating custom widgets/subclassing.
Needs some thinking about......
BTW, using xhtml you should not have valueless attributes. you should
say something like readonly="readonly", checked="checked" or some
such.
Regards,
Gary.
Well, if you'd put the above declarations _into_ the controller method, you
could do it - as python is scope-aware, and your fields and visibilities and
whatnot could easily be computed befor class-creation. After all, a class is
also just an object.
> Most, if not all of this should really be done in the controller
> without putting to much extra logic in the template. This way, you
> still only need ${form.display(value=myvalues)} in the template....
So it's not ok for you to write
${form.display(value=myvalues), **form_params}
where form_params is a controller-method created dictionary?
I accept that a syntax of
form.widget.property = value
is a bit nicer than
form_params['options']['widget'].property - but not _to_ much, and if you'd
really wanted, you could use python's __getitem__/__setitem__ and
__getattr__/__setattr__ functionalityes to achieve that above syntax close
enough, maybe with some additional magic for creating the top-level
options/attrs-keys. Maybe I think of something. Maybe not .. :)
> With the current widgets implementation this is not possible except by
> creating custom widgets/subclassing.
>
> Needs some thinking about......
Certainly :) I'm sorry if this sounds rude or harsh, it's certainly not meant
that way - but all you need is some mind-wrapping IMHO. I'v been doing a
mid-sized TG-project the pasts few months, and so far it beated the hell of
evrything else wrt to productivity. There are some quirks, and I admit that
programming with widgets is something that requires that you shouldn't be
afraid of looking into the code of turbogears. But so far, it solved all my
problems, and most of the time more on the elegant side of life.
Diez
Yeah, I'm trying that aproach now. I had thought about this, but don't
like the runtime performance hit of creating the widgets for each
request. It does give the maximum flxibility at runtime though.
I think I'll still persue the approach of statically creating the
widget list, but somehow taking a copy of the widgets at runtime as a
mutable set of widgets, it should be a fair bit faster then
contstructing them each time. I think that most of the hit in
constructing a widget is in the kid template compilation anyway.
> Certainly :) I'm sorry if this sounds rude or harsh, it's certainly not meant
> that way - but all you need is some mind-wrapping IMHO. I'v been doing a
> mid-sized TG-project the pasts few months, and so far it beated the hell of
> evrything else wrt to productivity. There are some quirks, and I admit that
> programming with widgets is something that requires that you shouldn't be
> afraid of looking into the code of turbogears. But so far, it solved all my
> problems, and most of the time more on the elegant side of life.
>
No, not rude or harsh at all. I'd sooner someone tell be to stop being
so damn stupid and/or tell me the bleedin obvious way to do it rather
than not say anything at all.
This is why I'm asking more TG experienced people like yourself for
better ways of doing things :) I know I also must sound a bit stupid
sometimes, but I'm just trying to explore all the possiblities and
make the right choices early in the project. I think that most people
would agree that the TG docs are not what they could be so the only
real way to find some of this out is read the code, try things and ask
people. I value your answers. Hopefully, when I find the "right"
answer I will update the docs.
I've done very large projects in ASP.NET, but this concept of one
static class shared between threads just takes some mind bending. I'm
still surprised that widgets (or more directly forms) work (or at
least are recommended to be used) this way. It seems that many people
are getting tripped up by this and each one has their own way of
working around the same limitation. Kind of begs for a more general
solution in the widgets architecture (by somewone cleverer than me for
sure!).
Thanks again for your feedback,
Gary.
But the template will be compiled and cached. Not much of a penalty there.
> This is why I'm asking more TG experienced people like yourself for
> better ways of doing things :) I know I also must sound a bit stupid
> sometimes, but I'm just trying to explore all the possiblities and
> make the right choices early in the project. I think that most people
> would agree that the TG docs are not what they could be so the only
> real way to find some of this out is read the code, try things and ask
> people. I value your answers. Hopefully, when I find the "right"
> answer I will update the docs.
You are right regarding the docs, but then - I always only trust the code...
> I've done very large projects in ASP.NET, but this concept of one
> static class shared between threads just takes some mind bending. I'm
> still surprised that widgets (or more directly forms) work (or at
> least are recommended to be used) this way. It seems that many people
> are getting tripped up by this and each one has their own way of
> working around the same limitation. Kind of begs for a more general
> solution in the widgets architecture (by somewone cleverer than me for
> sure!).
You always have to make a choice what to keep static and what dynamic. It
might be that there could be workarounds that allow for what you ache for,
but then that would come with another burden - even more metaclass and
descriptor magic.
Diez
> BTW I just had a peek at the Django newforms widgets (fields). It
> seems they had a similar problem. It looks like it was solved by
> creating the form definition statically (like TG) but at runtime the
> user creates an instance of the form. At instance construction the
> form copies its class field attributes into instance fields attributes
> (self.fields) so that they can be modified at runtime without
> affecting any other form instance. This seems to work for statically
> declaring the form but is efficient and flexible at runtime as the
> form "definition" (the list of widgets etc.) is copied to a mutable
> instance.
And how they validate that the submitted form is respecting the business rules
for that condition? They rebuild the widget when validating it so that they
can apply the same rules? Or the developer has to code this somehow when
processing the information sent?
--
Jorge Godoy <jgo...@gmail.com>
Hmm, there certainly seems to be. As a test I'm creating a list of 10
widgets in the request handler (but not displaying them). Just
creating the widgets every time adds about 30 ms to each request. If
in each of these widgets I then pass template=None, then a negligble
amount of time is added to the original request time for the
construction of the same 10 widgets each time. Looking through the
widget code I see that the only call that would be left out in this
test would be the load_kid_template call in the base widget class.
I would have thought that in creating separate instances of the
widgets at runtime the kid template would have to be loaded (and
discarded) every time with the widget. I think that kid only disk-
caches templates that are already stored on the disk as .kid files.
This is not the case for most of the widgets.
Unless I'm wrong again of course.....
Regards,
Gary.
Yes, it certainly seems that way as far as I can see. The form needs
to be re-constructed at POST time and the POSTed dictionary passed
into it for validation. The form instance can then be re-used to
display the values plus validation errors if the validation fails.
This doesn't seem to take much runtime overhead as the field copy
operation is pretty quick.
Regards,
Gary.
> --
> Jorge Godoy <jgo...@gmail.com>
Ah, that might be the case - I've been playing around with the disk-based
kid-templates because of i18n-issues with performance, so I know for sure
that these are compiled once and reused (until file changes are detected of
course).
But for the mostly inlined templates of widgets, that doesn't seem to be true.
Diez
>I.e. I would like to "create" a form instance, modify a few bits
>(perhaps) then send it to the template for display together with the
>values as per now.
>
>
The TG way to do this is to create a static form instance. Then, in the
controller create a params dict with your specific options. Pass both
the form and the params to the template. In the template do something
like $form(params=params)
With this approach, TG widgets should be just as flexible as the
alternatives you mentioned. I'll avoid getting into a debate about which
approach is better :-)
Paul