Add class to form field Django ModelForm

你说的曾经没有我的故事 提交于 2019-12-04 16:41:44

问题


I am trying to write a Bootstrap Form with Django ModelForm. I have read the Django Documentation Django Documentation about Forms, so I have this code:

<div class="form-group">
{{ form.subject.errors }}
<label for="{{ form.subject.id_for_label }}">Email subject:</label>
{{ form.subject }}</div>

The {{form.subject}} is rendered by Django, for example in CharField field model, as input tag,

<input type="text"....> etc.

I need add "form-control" class to every input in order to get Bootstrap input appearance (without third-party packages). I found this solution Django add class to form field. Is there any way to add a class to every field by default without specifying it in every attribute of the class of Form class?

class ExampleForm(forms.Form):
   name = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
   email = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
   address = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
   country = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))

and so on ..

Thanks in advance.


回答1:


If you can't use a third-party app and want to add a class (e.g., "form-control") to every field in a form in a DRY manner, you can do so in the form class __init__() method like so:

class ExampleForm(forms.Form):
    # Your declared form fields here
    ...

    def __init__(self, *args, **kwargs):
        super(ExampleForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

You might need to handle checking for existing classes in attrs too, if for some reason you'll be adding classes both declaratively and within __init__(). The above code doesn't account for that case.

Worth mentioning:

You specified that you don't want to use third-party packages. However, I'll take one second to mention that one of the simplest ways of automatically making forms render in the style of Bootstrap is to use django-crispy-forms, like this:

# settings.py
CRISPY_TEMPLATE_PACK = 'bootstrap3'

# forms.py
from crispy_forms.helper import FormHelper
class ExampleForm(forms.Form):
    # Your declared form fields here
    ...
    helper = FormHelper()

# In your template, this renders the form Bootstrap-style:
{% load crispy_forms_tags %}
{% crispy form %}



回答2:


you can add CSS classes in forms.py

subject = forms.CharField(label='subject', max_length=100 , widget=forms.TextInput(attrs={'class': "form-control"}))



回答3:


Crispy forms are the way to go . Tips for Bootstrap 4. Adding to @Christian Abbott's answer, For forms , bootstrap says, use form-group and form-control . This is how it worked for me .

My forms.py

class BlogPostForm(forms.ModelForm):
    class Meta:
        model = models.Post
        fields = ['title', 'text', 'tags', 'author', 'slug']
    helper = FormHelper()
    helper.form_class = 'form-group'
    helper.layout = Layout(
        Field('title', css_class='form-control mt-2 mb-3'),
        Field('text', rows="3", css_class='form-control mb-3'),
        Field('author', css_class='form-control mb-3'),
        Field('tags', css_class='form-control mb-3'),
        Field('slug', css_class='form-control'),
    )

My post_create.html

{% extends 'blog/new_blog_base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">

<form method='POST' enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.media }}
    {% crispy form %}

<hr>
<input type="submit" name="Save" value="Save" class='btn btn-primary'> <a href="{% url 'home' %}" class='btn btn-danger'>Cancel</a>
</form>

</div>
{% endblock %}

Note : If you are using CK Editor RichTextField() for your model field , then that field wont be affected . If anyone knows about it , do update this .




回答4:


One way is to create base form class and manually update the field's attribute inside __init__ method.

Another is by using already existing libraries like this one: https://github.com/dyve/django-bootstrap3

There are plenty of these libraries around github. Look around.




回答5:


I know that author asked about Bootstrap for own Form, but there is an additional way to include Bootstrap class tag in Django form for authentication, password reset etc.

If we create template with standard form:

<form action="" method="post">
   {% csrf_token %}
   {{ form }}
</form>

then in browser source code we can see all the form fields with the tags:

<form action="" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="xxx">
    <tr><th><label for="id_old_password">Old password:</label></th><td><input type="password" name="old_password" autofocus required id="id_old_password"></td></tr>
    <tr><th><label for="id_new_password1">New password:</label></th><td><input type="password" name="new_password1" required id="id_new_password1"></td></tr>
    <tr><th><label for="id_new_password2">New password confirmation:</label></th><td><input type="password" name="new_password2" required id="id_new_password2"></td></tr>
</form>

Variable {{ form }} in our template now can be replaced with this code and Bootstrap classes we needed:

<div class="fieldWrapper form-group" aria-required="true">
    <label for="id_old_password">Old password:</label><span class="required">*</span>
    <input type="password" **class="form-control"** name="old_password" autofocus required id="id_old_password">
</div>

Maybe it could be useful for redesign built-in static forms.



来源:https://stackoverflow.com/questions/29716023/add-class-to-form-field-django-modelform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!