How do I add custom CSS to crispy forms?

我怕爱的太早我们不能终老 提交于 2021-02-07 09:08:32

问题


I'm trying to create a responsive form for my website with the help of crispy forms.I'm not using bootstrap and I want to add custom CSS to the crispy form to match my whole website.

HTML:

<form method='POST' action=''>{% csrf_token %}

            {{ form|crispy }}

                    <input type='submit' value='Sign Up' />



            </form>

using inspect element it shows:

            <form method='POST' action=''><input type='hidden' name='csrfmiddlewaretoken' value='GLJMxnnDz1MGNFC46pjoofSlo6JMCD1IXu7X3n7LsRbQfdS38SYHJMs9IAXddcck' />



<div id="div_id_full_name" class="form-group"> <label for="id_full_name" class="control-label ">
                Full name
            </label> <div class="controls "> <input class="textinput textInput form-control" id="id_full_name" maxlength="120" name="full_name" type="text" /> </div> </div> <div id="div_id_email" class="form-group"> <label for="id_email" class="control-label  requiredField">
                Email<span class="asteriskField">*</span> </label> <div class="controls "> <input class="emailinput form-control" id="id_email" maxlength="254" name="email" type="email" required /> </div> </div>


        <!--    <input class='btn btn-primary' type='submit' value='Sign Up' />-->
                        <input type='submit' value='Sign Up' />



            </form>

forms.py:

from django import forms

from .models import SignUp

class ContactForm(forms.Form):
    full_name = forms.CharField(required=False)
    email = forms.EmailField()
    message = forms.CharField()


class SignUpForm(forms.ModelForm):
    class Meta:
        model = SignUp
        fields = ['full_name', 'email']

models.py:

from __future__ import unicode_literals

# Create your models here.
from django.db import models

# Create your models here.
class SignUp(models.Model):
    email = models.EmailField()
    full_name = models.CharField(max_length=120, blank=True, null=True)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def __unicode__(self): #Python 3.3 is __str__
        return self.email

回答1:


As docs says, by default crispy forms using bootstrap, and also provides some template packs for bootstrap, bootstrap3, bootstrap4 and uni-form. see also about Overriding project templates

If you need to custom this crispy forms, you need to create a new custom template for your project, an example crispy_forms/templates/<foobar>/. you can checkout at this path of repository: https://github.com/django-crispy-forms/django-crispy-forms/tree/dev/crispy_forms/templates


But, previously crispy forms has templatetags to handle specific field. one of it is {{ form.field_name|as_crispy_field }}, this example below is output of it.

<div id="div_id_email" class="control-group">
  <label for="id_email" class="control-label">Email address</label>
  <div class="controls">
    <input class="form-control" id="id_email" maxlength="254" name="email" required="required" type="email" />
  </div>
</div>

Other options, you can handle it using specific html selectors/attributes inside your forms widget, such as html class, id, style, or else.

For example in your case;

class SignUpForm(forms.ModelForm):

    class Meta:
        model = SignUp
        fields = ['full_name', 'email']
        widgets = {
          'email': forms.EmailInput(attrs={'class': 'form-control custom-class'}),
        }

And then, if you render as {{ form.email|as_crispy_field }}, this should render the html;

<div id="div_id_email" class="control-group">
  <label for="id_email" class="control-label">Email address</label>
  <div class="controls">
    <input class="form-control custom-class" id="id_email" maxlength="254" name="email" required="required" type="email" />
  </div>
</div>

Crispy forms also provides simply configuration inside settings.py, Django fields generate default classes, crispy-forms handles these and adds other classes for compatibility with CSS frameworks. For example a CharField generates an <input class="textinput", for more...

CRISPY_CLASS_CONVERTERS = {
    'textinput': "form-control cst__radius",
    'urlinput': "form-control cst__radius",
    'numberinput': "form-control cst__radius",
    'emailinput': "form-control cst__radius",
    'dateinput': "form-control cst__radius",
    'textarea': "form-control cst__radius",
    'passwordinput': "form-control cst__radius",
    'select': "form-control cst__radius",
}



回答2:


You'd have to write your own CSS that would target each element of the Crispy form that you wanted to style.

Use the inspect element and find the ID/class of the element you want to work with. Write your styles in the inspect element window and once you're happy with it copy the code to a CSS file that will eventually be your "form override" file that will bring it's look more in line with the rest of your site.




回答3:


If you are targeting specifically the exact fields css (ex: input field class i.e <input class="your_custom_class" />) then try following snippets ( Without modifying Crispy helper):

Using Model Form:

class YourForm(ModelForm):
     def __init__(self, *args, **kwargs):
         self.fields['your_field'].widget.attrs['class']='your_custom_class'

Using Form:

class YourForm(forms.ModelForm):
     class Meta:
         model = YourModel
         fields = ['field1', 'field2']
         widgets = {
         'field1': forms.TextInput(attrs={'class': 'your_custom_class'}),
         }



回答4:


Crispy forms provides a framework for this.

First of all, you can tell crispy_forms to use 'bootstrap4' templates:

project/settings.py

# settings
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# other settings

That will render your buttons and inputs according to the Bootstrap 4 form templates

If you still want to apply styles to a specific input or button, you can use the Crispy FormHelper class and Layouts, which are, by the way, amazing.

forms.py

from crispy_forms.helper import FormHelper
from crispy_forms.layout import (
    Layout,
    Field,
    Submit,
)


class SignUpForm(forms.ModelForm):

    class Meta:
        model = SignUp
        fields = ['full_name', 'email']
        widgets = {
          'email': forms.EmailInput(attrs={'class': 'form-control custom-class'}),
        }

    def __init__(self, *args, **kwargs):
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
            'full_name',
            Field('email', css_class='custom-class')  # form-control will be provided by bootstrap templates
            Submit('submit', 'Sign Up', css_class='btn-primary')  # define your signup button here
        )

Next you can render your entire form using {% crispy form %}. The form tag and csrf_token will be created by default:

signup.html

{% load crispy_forms %}
{% crispy form %}

Result

<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<form action="" method="POST">
    <input type='hidden' name='csrfmiddlewaretoken' value='GLJMxnnDz1MGNFC46pjoofSlo6JMCD1IXu7X3n7LsRbQfdS38SYHJMs9IAXddcck' />
    
  <div class="form-group">
    <label for="id_full_name">Full Name</label>
    <input type="text" class="form-control" id="id_full_name">
  </div>

  <div class="form-group">
    <label for="id_email">Email <span class="required">*</span></label>
    <input type="email" class="form-control custom-class" id="id_email" required>
  </div>

  <button type="submit" class="btn btn-primary">Sign Up</button>

</form>



回答5:


Write CSS to target the rendered form elements (inspect these elements in chrome). Give the element a custom class like "crispy-form". For example, I managed to hide the label for an input text by:

HTML:

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

CSS:

.crispy-form label {
    display: none;
}


来源:https://stackoverflow.com/questions/42491691/how-do-i-add-custom-css-to-crispy-forms

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