Define css class in django Forms

前端 未结 13 672
南旧
南旧 2020-11-27 10:11

Assume I have a form

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.Boolea         


        
相关标签:
13条回答
  • 2020-11-27 10:22

    In case that you want to add a class to a form's field in a template (not in view.py or form.py) for example in cases that you want to modify 3rd party apps without overriding their views, then a template filter as described in Charlesthk answer is very convenient. But in this answer the template filter overrides any existing classes that the field might has.

    I tried to add this as an edit but it was suggested to be written as a new answer.

    So, here is a template tag that respects the existing classes of the field:

    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})
    
    0 讨论(0)
  • 2020-11-27 10:23

    Answered my own question. Sigh

    http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs

    I didn't realize it was passed into the widget constructor.

    0 讨论(0)
  • 2020-11-27 10:23

    Use django-widget-tweaks, it is easy to use and works pretty well.

    Otherwise this can be done using a custom template filter.

    Considering you render your form this way :

    <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 is an instance of BoundField which has the as_widget method.

    you can create a custom filter "addcss" in "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', '').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})
    

    And then apply your filter:

    {% 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 will then be rendered with the "MyClass" css class.

    Hope this help.

    EDIT 1

    • Update filter according to dimyG's answer

    • Add django-widget-tweak link

    EDIT 2

    • Update filter according to Bhyd's comment
    0 讨论(0)
  • 2020-11-27 10:24

    Expanding on the method pointed to at docs.djangoproject.com:

    class MyForm(forms.Form): 
        comment = forms.CharField(
                widget=forms.TextInput(attrs={'size':'40'}))
    

    I thought it was troublesome to have to know the native widget type for every field, and thought it funny to override the default just to put a class name on a form field. This seems to work for me:

    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'
    

    This seems a little cleaner to me.

    0 讨论(0)
  • 2020-11-27 10:29

    If you want all the fields in the form to inherit a certain class, you just define a parent class, that inherits from forms.ModelForm, and then inherit from it

    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
    

    This helped me to add the 'form-control' class to all of the fields on all of the forms of my application automatically, without adding replication of code.

    0 讨论(0)
  • 2020-11-27 10:33

    Simply add the classes to your form as follows.

    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'
            }
        ))
    
    0 讨论(0)
提交回复
热议问题