Common patterns for using `django-crispy-forms`?

context:

  • using django-crispy-forms with crispy-daisyui
  • I’m learning about the |crispy filter vs the {% crispy %} tag and related topics
  • I think I now understand the basics of “how” to implement in different ways, but I’m struggling with the “when/why” to choose which options, and I want to see if the general consensus I’m piecing together is on the right track

Summary of learnings / clarifying questions:

  • the |crispy filter is meant for use with the simplest forms and you don’t customize it at all (it just makes it prettier via whatever the template pack defaults). This generally means that people quickly move to using the `{% crispy %}` tag simply because it allows for more customization. Is that accurate?
  • the phrase “programmatic layout“ was used in the django-crispy-forms docs and, based on context from other sources, I’m gathering that to have a programmatic layout means that the layout stuff (like the placement fields in a form are displayed) is defined in a .py file instead of the .html template file like would be the normal home of stuff like that. Is that accurate?
    • Relatedly, someone implied that there’s two general camps of thought for this topic: one group that doesn’t like defining layout (and maybe also any styling-related stuff like tailwind classes at all, though I’m not sure how far it goes) in anything other than the .html template and one group that, when using django-crispy-forms, likes to have all the form stuff defined in the forms.py using FormHelper/Layout so the template just needs the `{% crispy %}` tag. I’m wondering:
      • are these two camps of similar size or is one of the camps more prevalent/common?
      • would someone in the first camp that likes layout stuff in the template still use django-crispy-forms or is it kind of like the benefits of using django-crispy-forms is diminished enough that if you don’t use the second camp’s philosophy of taking advantage of FormHelper/ Layout then it’s kind of not worth it to used?

I’m looking for corrections and/or opinions for what’s most typically done and/or how you personally prefer to do things.

Thanks as always, curious to learn more

Wow! Great topic and really good questions.

First, my “obligatory disclaimer”:
<opinion>
What follows are the thoughts and opinions of one atypical user.

I’ve also considered considered it as a bridge between what you have now and what you want to get to.

The filter is easiest if you already have forms and templates fully defined, and you currently render the form as {{ form }}. All you need to do is change it to {{ form|crispy }} to apply the defaults to the form. You can then (over time) migrate your forms to a more complete crispy-based implementation as desired (or warranted).

Yes. I run a system that uses a relatively few Form classes. The fields and layouts in those forms is generated dynamically based on need. This avoids either creating N Form classes and their corresponding templates, or creating templates with multiple conditionals identifying what fields are being displayed. (Think of a survey or registration form where the questions to be asked depend upon the combination of previously-supplied answers.)

The form layout gets created by the form based upon the fields to render supplied to it by the view, all defined dynamically based upon data.

(Note, not directly related to this, but I create these forms as HTML fragments that update the page using HTMX. The forms aren’t part of a full page. They’re also sent out to the browser through a websocket rather than using AJAX-style calls.)

Could I do all this using normal templates, forms, and views? Absolutely.

However, I greatly prefer writing something like:

Div(
    Row(
        Column(
	        Row('field_1'),
		    Row('field_2'),
		    Row('field_3'),
			css_id='col-1',
			css_class='left-col'
	    ),
		Column(
		    Row('field_4'),
			Row('field_5'),
			css_id='col-2',
			css_class='right-col'
		)
	)
)

instead of the html that I would need to write to create a similar layout.
</opinion>

1 Like

@StephanieAG

django-crispy-forms is built many years ago and I think some of the concepts of it is not very good option for today’s project

I have seen many people directly write form field code in page template, which I think it is bad pattern.

You can take a look at GitHub - rails-inspire-django/django-formify: Django-Formify seamlessly integrates Tailwind CSS styles into your Django forms for a modern look. · GitHub I have used it in some of my Django/Tailwind project as form solution, and I think it will be working with daisyui

If you want to check form demo, here it is: Django Lookbook

If you have any question, please feel free to ask.

Thx.

Thanks, @michael-yin

django-formify and its lookbook seem neat, nice work on it and glad it’s working for you. I’m confused why you mention django-crispy-forms as not a good option when django-formify is a fork of crispy-tailwind which is a template pack of django-crispy-forms (so doesn’t that mean django-formify still uses django-crispy-forms as its basis anyway?)

regarding:

I have seen many people directly write form field code in page template, which I think it is bad pattern.

can you expand on this? For example, you mention this as the bad pattern, but what is the “good pattern” that you would recommend and why is it better?

I tend to avoid programmatic layouts (meaning I don’t use them). To avoid that in the context of crispy-forms, I make heavy use of `|as_crispy_field` template tag. That way I can keep my `` layouts where it belongs (templates). E.g.

<div class="row">
    <div class="col-6">
        {% form.field_1|as_crispy_field %}
    </div>
    <div class="col-6">
        {% form.field_2|as_crispy_field %}
    </div>
</div>

To have more control, I’m migrating all my form components to django-cotton. Not 100% migrated yet since I have to, almost, re-implement Django fields logic (I guess).

2 Likes

If you are building with Tailwind and crispy-tailwind, you will find it is not easy to do customization, sometimes it is very tricky.

So many developers do not use crispy-tailwind to render the form, but use django-widget-tweaks directly set tailwind css class in the page template, for example, login.html, this makes the form style in the whole page not easy to maintain.

”django-formify” import server side components to make the customization work on component level instead of pure Django templates. BTW, it works better with custom form widget, as you can see in the above demo page.

1 Like