python - tweaks - Definir clase css en django Forms
submit django form (12)
Asumir que tengo un formulario
class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
django_hacker = forms.BooleanField(required=False)
¿Hay alguna manera de definir clases de CSS en cada campo para poder utilizar jQuery en función de la clase en mi página representada?
Esperaba no tener que compilar manualmente el formulario.
Ampliando el método apuntado a docs.djangoproject.com:
class MyForm(forms.Form):
comment = forms.CharField(
widget=forms.TextInput(attrs={''size'':''40''}))
Pensé que era problemático tener que conocer el tipo de widget nativo para cada campo, y me pareció divertido anular el valor predeterminado solo para poner un nombre de clase en un campo de formulario. Esto parece funcionar para mí:
class MyForm(forms.Form):
#This instantiates the field w/ the default widget
comment = forms.CharField()
#We only override the part we care about
comment.widget.attrs[''size''] = ''40''
Esto me parece un poco más limpio.
Aquí hay otra solución para agregar definiciones de clases a los widgets después de declarar los campos en la clase.
def __init__(self, *args, **kwargs):
super(SampleClass, self).__init__(*args, **kwargs)
self.fields[''name''].widget.attrs[''class''] = ''my_class''
Aquí hay una manera simple de alterar a la vista. agregue abajo a la vista justo antes de pasarlo a la plantilla.
form = MyForm(instance = instance.obj)
form.fields[''email''].widget.attrs = {''class'':''here_class_name''}
Aquí hay una variación de lo anterior que dará a todos los campos la misma clase (por ejemplo, jquery nice esquinas redondeadas).
# Simple way to assign css class to every field
def __init__(self, *args, **kwargs):
super(TranslatedPageForm, self).__init__(*args, **kwargs)
for myField in self.fields:
self.fields[myField].widget.attrs[''class''] = ''ui-state-default ui-corner-all''
Como resultado, puedes hacer esto en el constructor de formularios (función init ) o después de que se haya iniciado la clase de formulario. Esto a veces se requiere si no está escribiendo su propio formulario y ese formulario proviene de otro lado:
def some_view(request):
add_css_to_fields = [''list'',''of'',''fields'']
if request.method == ''POST'':
form = SomeForm(request.POST)
if form.is_valid():
return HttpResponseRedirect(''/thanks/'')
else:
form = SomeForm()
for key in form.fields.keys():
if key in add_css_to_fields:
field = form.fields[key]
css_addition = ''css_addition ''
css = field.widget.attrs.get(''class'', '''')
field.widget.attrs[''class''] = css_addition + css_classes
return render(request, ''template_name.html'', {''form'': form})
En caso de que quiera agregar una clase al campo de un formulario en una plantilla (no en view.py o form.py), por ejemplo, en casos en que quiera modificar aplicaciones de terceros sin anular sus vistas, entonces un filtro de plantilla como se describe en Charlesthk la answer es muy conveniente. Pero en esta respuesta, el filtro de plantilla anula cualquier clase existente que tenga el campo.
Traté de agregar esto como una edición, pero se sugirió que se escribiera como una nueva respuesta.
Entonces, aquí hay una etiqueta de plantilla que respeta las clases existentes del campo:
from django import template
register = template.Library()
@register.filter(name=''addclass'')
def addclass(field, given_class):
existing_classes = field.field.widget.attrs.get(''class'', None)
if existing_classes:
if existing_classes.find(given_class) == -1:
# if the given class doesn''t exist in the existing classes
classes = existing_classes + '' '' + given_class
else:
classes = existing_classes
else:
classes = given_class
return field.as_widget(attrs={"class": classes})
Otra solución que no requiere cambios en el código python es mejor para los diseñadores y los cambios de presentación excepcionales: django-widget-tweaks . Espero que alguien lo encuentre útil.
Respondió mi propia pregunta. Suspiro
docs.djangoproject.com/en/dev/ref/forms/widgets/…
No me di cuenta de que se pasó al constructor de widgets.
Si desea que todos los campos del formulario hereden una determinada clase, solo debe definir una clase principal, que hereda de forms.ModelForm
, y luego heredar de ella
class BaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BaseForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs[''class''] = ''someClass''
class WhateverForm(BaseForm):
class Meta:
model = SomeModel
Esto me ayudó a agregar la clase ''form-control''
a todos los campos en todas las formas de mi aplicación automáticamente, sin agregar replicación de código.
Simplemente agregue las clases a su formulario de la siguiente manera.
class UserLoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(
attrs={
''class'':''form-control'',
''placeholder'':''Username''
}
))
password = forms.CharField(widget=forms.PasswordInput(
attrs={
''class'':''form-control'',
''placeholder'':''Password''
}
))
También puede usar Django Crispy Forms , es una gran herramienta para definir formularios en caso de que quiera utilizar algún marco CSS como Bootstrap o Foundation. Y es fácil especificar las clases para sus campos de formulario allí.
A su clase de formulario le gustaría esto entonces:
from django import forms
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions
class SampleClass(forms.Form):
name = forms.CharField(max_length=30)
age = forms.IntegerField()
django_hacker = forms.BooleanField(required=False)
helper = FormHelper()
helper.form_class = ''your-form-class''
helper.layout = Layout(
Field(''name'', css_class=''name-class''),
Field(''age'', css_class=''age-class''),
Field(''django_hacker'', css-class=''hacker-class''),
FormActions(
Submit(''save_changes'', ''Save changes''),
)
)
Use django-widget-tweaks , es fácil de usar y funciona bastante bien.
De lo contrario, esto se puede hacer utilizando un filtro de plantilla personalizado.
Teniendo en cuenta que rinde su forma de esta manera:
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
</form>
form.subject es una instancia de BoundField que tiene el método as_widget .
puede crear un filtro personalizado "addcss" en "my_app / templatetags / myfilters.py"
from django import template
register = template.Library()
@register.filter(name=''addcss'')
def addcss(value, arg):
css_classes = value.field.widget.attrs.get(''class'', None).split('' '')
if css_classes and arg not in css_classes:
css_classes = ''%s %s'' % (css_classes, arg)
return value.as_widget(attrs={''class'': css_classes})
Y luego aplica tu filtro:
{% load myfilters %}
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject|addcss:''MyClass'' }}
</div>
</form>
form.subjects se representará con la clase css "MyClass".
Espero que esto ayude.
EDITAR
Actualizar filtro según la respuesta de dimyG
Añadir el enlace django-widget-tweak