django crispy forms with jinja2

后端 未结 4 1038
心在旅途
心在旅途 2020-12-14 23:31

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:

相关标签:
4条回答
  • 2020-12-14 23:45

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

    0 讨论(0)
  • 2020-12-14 23:46

    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.

    0 讨论(0)
  • 2020-12-14 23:52

    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.

    0 讨论(0)
  • 2020-12-15 00:07

    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) }}
    
    0 讨论(0)
提交回复
热议问题