is there any possibility in django to put a widget into a model
instead of creating the whole forms for each model (using widgets
render)? I only need to add a css class to each field in a model...
Best regards
If so, you could make a small `base class`_ to do that::
class BaseYourForm(forms.BaseForm):
def __init__(self, *args, **kwargs):
super(BaseYourForm, self).__init__(*args, **kwargs)
for i in self.fields:
self.fields[i].widget.attrs['class'] = 'yourclassname'
Then just create your form with that one extra argument::
YourForm = form_for_model(YourModel, form=BaseYourForm)
There may be a better way to do that, but it works for me. :-)
Don't forget about the `fields argument`_ if you only want a few of
your model's fields to show up in the form::
YourForm = form_for_model(YourModel, fields=dictOfYourFields,
form= BaseYourForm)
.. base class: http://www.djangoproject.com/documentation/newforms/#using-an-alternate-base-class
.. fields argument: http://www.djangoproject.com/documentation/newforms/#using-a-subset-of-fields-on-the-form
Cheers.
- whiteinge
Something like that should be nice:
list_of_required = ['name', 'username']
MyForm = form_for_model(MyModel, form=
BaseYourForm(list_of_required))
Hm. I guess that I only have to modify the loop:
for i in self.fields:
self.fields[i].widget.attrs['class'] =
'yourclassname'
But what's the name of field ? i.name ? or what ?
You can replace the loop with explicit calls for each field::
self.fields['name'].widget.attrs['class'] = yourClass1
self.fields['username'].widget.attrs['class'] = yourClass2
Or if you want to pass a list in as an argument just pop() it before
calling super()::
class BaseYourForm(forms.BaseForm):
def __init__(self, *args, **kwargs):
tmpVariable = kwargs.pop('yourListofFields', False)
super(BaseYourForm, self).__init__(*args, **kwargs)
for i in tmpVariable:
self.fields[i].widget.attrs['class'] =
'yourclassname'
You were close by passing your list of fields to the base form you
created, but you actually need to pass it when you instantiate your
form::
YourForm = form_for_model(YourModel, form=BaseYourForm)
list_of_required = ['name', 'username']
form = YourForm(yourlistoffields=list_of_required)
Cheers.
- whiteinge
Model looks like that:
class ShortNews(models.Model):
url = models.URLField("URL")
description = models.CharField("Desc", maxlength="200")
author = models.ForeignKey(User, editable=False)
date = models.DateTimeField("Date", auto_now_add=True)
status = models.IntegerField("Status", editable=False, default="0")
and I don't know why it is not possible to do sth like:
class ShortNews(models.Model):
url = models.URLField("URL", attr['class':'required'])
description = models.CharField("Desc", maxlength="200",
attr['class':'highlight'])
..etc
It's much faster than doing that at every form_for_* and you don't
have to have it spread all over the code. But the point is, that I
don't know if there is something which can allow to do that :)
Thanks,
l5x
If you find yourself having to do this sort of thing a lot, I would
suggest putting those BaseForm class definitions right next to the
model class in models.py. I do a similar thing with Managers. You
could even put the list of elements that need custom CSS classes
directly in your model. Or, better yet, make it a dictionary like
{ 'element: 'classname' }. Or even better still, maybe you could do
something like this in your model::
@property
def custom_class_list(self):
# you might have to strip out 'id' from this list
return [i.name for i in self._meta.fields]
And then just have a generic BaseForm that you use with all your
form_for_* generated-forms.
.. __: http://groups.google.com/group/django-users/msg/74aaef38380f2c31
Cheers.
- whiteinge
No, it isn't possible and that's by design. Here's the reasoning behind
why we are doing it the way we are:
In the general case ,tying a particular presentation to the data
representation isn't a flexible procedure and long-term in medium to
large projects, not great design practice either: the person responsible
for creating the form designs has to also edit the code that is part of
the data representation. We try very hard in Django (and are continually
smoothing out places as we go along) to keep independent
responsibilities separate in the code and this includes moving
presentation information out of models.
We have to make a choice when creating the API here and, as with all
choices, some use-cases might become a little harder (but never
impossible) whilst we are making the common and best-practice cases
easier. In this particular instance, the case where you have a single
presentation style and are always creating forms directly from a single
model requires you to write the field names twice sometimes. That's one
of the trade-offs in the broader design, unfortunately.
Consequently, you can't drop presentation information into the model
directly. However, you could store a list of that extra information
mapped to field names in a dictionary and then write a helper function
that takes your model and that dictionary and creates a form. So if you
did have a desire to keep the information together, it's possible. You
just can't hijack the Field class definitions to store it, because that
would require changing the API (you could write new classes, one for
each Field that takes the extra information, but at some point the extra
work to support that might become onerous).
Regards,
Malcolm
On Jun 25, 3:19 am, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote: