django crispy forms with jinja2
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.
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) }}
I found an easy, but not completed way to "hack in".
- use 'django-jinja' package to register new filters;
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.