Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django crispy forms with jinja2

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?

like image 500
eiscalle Avatar asked Aug 18 '14 13:08

eiscalle


4 Answers

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.

like image 148
Sad Pencil Avatar answered Oct 19 '22 10:10

Sad Pencil


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) }}
like image 39
nex2hex Avatar answered Oct 19 '22 10:10

nex2hex


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.

like image 2
user1232028 Avatar answered Oct 19 '22 10:10

user1232028


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

like image 1
Geoffrey R. Avatar answered Oct 19 '22 09:10

Geoffrey R.