[Solved]-Django crispy forms with jinja2

12👍

Better solution:

templatetags.py

from crispy_forms.utils import render_crispy_form
from django_jinja import library
from jinja2 import contextfunction


@contextfunction
@library.global_function
def crispy(context, form):
    return render_crispy_form(form, context=context)

In template:

{{ crispy(form) }}

4👍

Well, Geoffrey R.’s answer is a good approach, but the wrong method of jinja2 is used. Instead of render_crispy_form, it should be as_crispy_form. So, from crispy_forms.templatetags.crispy_forms_filters import as_crispy_form should be written at the beginning.

The corrected example jinja2.py file is as follows.

from crispy_forms.templatetags.crispy_forms_filters import as_crispy_form # this line is different

from django.contrib import messages
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from django.utils import translation
from jinja2 import Environment


def environment(**options):
    env = Environment(
        extensions=["jinja2.ext.i18n", "jinja2.ext.with_"], **options
    )
    env.globals.update(
        {
            "get_messages": messages.get_messages,
            "static": staticfiles_storage.url,
            "crispy": as_crispy_form,  # this line is different
            "url": reverse,
        }
    )
    env.install_gettext_translations(translation)
    return env

Other steps are same with Geoffrey R.’s answer.


It works for me, with the following pip packages:

Django==3.1.2
django-crispy-forms==1.9.2
Jinja2==2.11.2

By the way, I’m not using the django-jinja pip package.

Thanks Geoffrey R. for his great idea.

2👍

I found an easy, but not completed way to “hack in”.

  1. use ‘django-jinja’ package to register new filters;
  2. in the filter file, define a crispy filter, which looks like:

    from crispy_forms.templatetags.crispy_forms_filters import as_crispy_form
    def crispy(form):
        return as_crispy_form(form, 'Bootstrap3', form.helper.label_class, form.helper.field_class)
    

In the form Jinja template, I have to write more code than direct crispy tag in django template:

<form id='id_form' class="form-horizontal" method='post'>
    {% csrf_token %}
    {{form.media}}
    {{ form|crispy() }}
    <div>
        <input type="submit" name="submit" value="Submit" class="btn btn-primary" id="submit-id-submit">
    </div>
</form>

If anyone finds a more effective way to crispy forms, please let me know.

1👍

I have been struggling with this issue of yours and the given answer, although they might be relevant a few years ago, did not satisfy me.

So I went myself building a hack to make crispy forms work with Django 3.0.2 (I did not test the others versions, please let me know guys if there is any issue on any other version).

Install the relevant packages to make crispy forms work with Jinja2 :

pip install django-crispy-forms django-jinja

In your project directory (and NOT your application directory), make sure you have a jinja2.py file with:

from crispy_forms.utils import render_crispy_form

from django.contrib import messages
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from django.utils import translation
from jinja2 import Environment


def environment(**options):
    env = Environment(
        extensions=["jinja2.ext.i18n", "jinja2.ext.with_"], **options
    )
    env.globals.update(
        {
            "get_messages": messages.get_messages,
            "static": staticfiles_storage.url,
            "crispy": render_crispy_form,  # THIS LINE IS RELEVANT
            "url": reverse,
        }
    )
    env.install_gettext_translations(translation)
    return env

Make sure that your jinja2 template engine loads this option in your django’s settings:

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.jinja2.Jinja2",
        "DIRS": [os.path.join(BASE_DIR, "jinja2")],
        "APP_DIRS": True,
        "OPTIONS": {"environment": "your_django_project.jinja2.environment"},
    },
    # ...

Note the "crispy": render_crispy_form, which will help you use crispy forms in your jinja2 templates.

Then, in your template, you can use:

{{ crispy(form) }}

Leave a comment