widgets formularios formmodel form fields create combofield django django-forms

formularios - ¿Cómo configuro los atributos de widget predeterminados para un Django ModelForm?



formularios django (5)

Me gustaría establecer el atributo de clase para el widget TextInput en un valor para todos los campos de mi formulario que lo utilicen sin tener que enumerarlos todos en Meta: widgets = {.... ¿Es esto posible?

Gracias.


Crea un nuevo widget con tu clase de CSS:

class PrettyWidget(forms.TextInput): class Media: css = { ''all'': (''pretty.css'',) }

En su forma, use su nuevo widget en todos sus campos:

class ContactForm(forms.Form): subject = TextField(widget=PrettyWidget)


Una cosa que hice en el pasado es crear una función lambda que devuelva los campos que uso a menudo:

from django import forms fancy = lambda: forms.TextInput(attrs={''class'': ''derp''}) class MyForm(forms.Form): attr1 = fancy() attr2 = fancy() attr3 = fancy()

No recuerdo por qué exactamente opté por usar una función para manejar mi situación, pero sospecho que tuvo algo que ver con la creación de instancias separadas del objeto forms.TextInput para cada campo de formulario ....


Puedes usar lo siguiente:

def set_attrs_for_fields(fields, default_attrs): for field_name in fields: field = fields[field_name] try: default_widget_attr = default_attrs[field.widget.__class__] field.widget.attrs = default_widget_attr except KeyError: pass class DefaultAttrForm(forms.Form): def __init__(self, *args, **kwargs): super(DefaultAttrForm, self).__init__(*args, **kwargs) set_attrs_for_fields(self.fields, self.get_default_attrs()) def get_default_attrs(self): '''''' Child class should overwrite this method and return dict with example format {forms.TextInput: {''class'': ''my_value''}} where keys, are widget classes for which default attrs will be set. '''''' raise NotImplementedError() class DefaultAttrModelForm(ModelForm): def __init__(self, *args, **kwargs): super(DefaultAttrModelForm, self).__init__(*args, **kwargs) set_attrs_for_fields(self.fields, self.get_default_attrs()) def get_default_attrs(self): '''''' Child class should overwrite this method and return dict with example format {forms.TextInput: {''class'': ''my_value''}} where keys, are widget classes for which default attrs will be set. '''''' raise NotImplementedError()

Ahora, cada vez que quiera usar attrs predeterminados para algún widget, solo necesita crear una clase que herede de DefaultAttrForm o DefaultAttrModelForm y sobrescribir el método get_default_attrs . Ejemplo para la forma normal de Django:

class MyForm(DefaultAttrForm): my_field1 = forms.CharField(widget=forms.TextInput()) my_field2 = forms.CharField(widget=forms.PasswordInput(attrs={''my_non_default'': ''Non default''})) def get_default_attrs(self): # all fields with widget TextInput will have # default attrs set to {''class'': ''my_value''} return {forms.TextInput: {''class'': ''my_value''}, } In [1]: form = MyForm() In [2]: form.fields[''my_field1''].widget.attrs Out[2]: {''class'': ''my_value''} In [3]: form.fields[''my_field2''].widget.attrs Out[3]: {''my_non_default'': ''Non default''}

Para el uso de la forma de modelo siguiente:

class MyModelForm(DefaultAttrModelForm): class Meta: model = my_model def get_default_attrs(self): # all fields with widget TextInput will have # default attrs set to {''class'': ''my_value''} return {forms.TextInput: {''class'': ''my_value''}, } In [1]: form = MyModelForm() In [2]: form.fields[''my_field1''].widget.attrs Out[2]: {''class'': ''my_value''} In [3]: form.fields[''my_field2''].widget.attrs Out[3]: {''my_non_default'': ''Non default''}


Para ModelForm podemos usar esto.

from django import forms from django.contrib.auth.models import User class UserForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) # change a widget attribute: self.fields[''user_permissions''].widget.attrs["size"] = 5 self.fields[''user_permissions''].widget.attrs["class"] = ''form-control required'' class Meta: model = User


Puede anular el constructor para modificar todos los widgets TextInput:

from django import forms class MyForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(MyForm, self).__init__(*args, **kwargs) for name, field in self.fields.items(): if field.widget.__class__ == forms.widgets.TextInput: if ''class'' in field.widget.attrs: field.widget.attrs[''class''] += '' my-class'' else: field.widget.attrs.update({''class'':''my-class''}) class Meta: model = MyModel

¿Puedes anular init con un decorador? Además, debería haber una declaración if antes de attrs.update () porque quiero establecer un valor predeterminado en lugar de anular lo que ya puede estar allí. - Kevin

No probado, pero supongo que puedes heredar de MyForm si lo usas mucho.