7

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

5 Answers 5

7

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",
}
Sign up to request clarification or add additional context in comments.

8 Comments

the 'custom-class' ahould be in my main "style.css" file?
yes, you can custom your css style inside your style.css or wherever you need. example .custom-class {font-size: 12px}, but makesure the source of bootstrap is put before source of style.css
As I said, I'm not using bootstrap :/
But, if you need more complex stuff and confused, I suggest you to don't use it... I'll give you an example from my currently project pastebin.com/c0nc9GAc
yeah, without using crispy form. just custom the form as I need. you can read this docs docs.djangoproject.com/en/dev/topics/forms/…
|
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.

Comments

2

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.

In particular, note the .css_class='...' parameter, which renders into HTML as class="..."

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>

Comments

0

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'}),
         }

Comments

0

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.