django crispy forms with jinja2
Asked Answered
M

5

11

I want to use Jinja2 and Django crispy forms together, but when I load crispy_forms_tags in my template and trying to render form with this template tag, I get an error:

Encountered unknown tag 'crispy'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'.

My template code:

{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="panel-heading"><h3>Registration</h3></div>
    {% crispy form %}
{% endblock %}

How can I use this apps together?

Magnetic answered 18/8, 2014 at 13:49 Comment(1)
I guess you can't unless you write Jinja2 template tags for crispy forms. Django template tags will not work inside Jinja2 templates.Decommission
S
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) }}
Skardol answered 11/10, 2015 at 20:5 Comment(0)
W
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.

Windy answered 5/10, 2020 at 8:54 Comment(0)
B
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.

Butterandeggs answered 24/5, 2015 at 7:35 Comment(0)
C
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) }}

Conservation answered 19/1, 2020 at 14:42 Comment(0)
B
0

In more current versions, Django expects you to add the template engine options directly into the settings.py file.

In our case, we would handle it similarly. I'm also using the django_jinja package to help make life easier when integrating the two technologies.

TEMPLATES = [
    {
        "BACKEND": "django_jinja.jinja2.Jinja2",
        "DIRS": [
            BASE_DIR,
        ],
        "APP_DIRS": True,
        "OPTIONS": {
            "globals": {
                "crispy": "crispy_forms.utils.render_crispy_form",
            },
            "context_processors": [
                "django.contrib.auth.context_processors.auth",
                "django.template.context_processors.debug",
                "django.template.context_processors.i18n",
                "django.template.context_processors.media",
                "django.template.context_processors.static",
                "django.template.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
            ],
            "match_extension": ".html",
            "app_dirname": "jinja2",
        },
    },
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
Brackish answered 11/3 at 2:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.