Unopinionated form layout library

I’m using crispy forms but running daisy UI (built over tailwind), I find myself using django crispy exclusively for layouting as the daisy handles the UI logic.

However, I find myself practically building a custom crispy-daisy lib. Is there a way I can use crispy without UI libs and apply the CSS classes via the layoutHelper as needed?

I’m not sure I’m understanding exactly what you’re asking for here, so I may not be answering the right question.

Every layout object has a css_class attribute that can be used to assign css classes to those objects. (That’s the method we use. All our forms are organized as Layout objects.)

I am using the css_class for layouting. I’d like to know if there is a library that does something similar but is happy with just django’s default widgets instead of requiring us to use a CSS template pack as a peer dependency

From the django-crispy-forms installation guide,

You will need to install the appropriate template pack for your CSS framework and add it to your list of INSTALLED_APPS.

Note that the template packs primarily contain templates that use the relevant css from the libraries they are associated with. It’s really not all that difficult to create your own template pack for what you need, and customized for the css you want to use. See How to create your own template packs — django-crispy-forms 2.0 documentation

Bit of a late reply to this, but it’s the first result when looking for daisyui / django practices.

The documentation for crispy-forms just shows how to override the existing layout HTML stuff, afaik. But for example that list is missing textarea. So if I want to provide styling for that, I need to go into the actual python code of crispy-forms and create a whole new python package (as done by crispy-tailwind and crispy-daisy)

Or am I missing something and it should be easier now?

Welcome @cadolphs !

I was wondering if you would be more specific on what you’re looking to do here?

Between the layout objects and template overrides, I’ve always been able to apply whatever CSS classes I’ve wanted to use without creating new packages. However, I’m likely not doing what you’re wanting, and so it would be helpful if you could provide a more specific example.

Hi and thank you for the nice welcome.

I’m just getting a handle on how it all works together. I’m using TailwindCSS / DaisyUI for my CSS. I want to have a consistent style applied to forms without any extra work on my part (i.e. no FormHelper. Just out-of-the-box niceness.)

Now, setting up crispy-daisyui worked well, but I noticed a strange behavior for <textarea> elements: No matter what value I provide for the row attribute, it would only ever render as a one-line field.

Some digging showed me that, in the crispy forms, it would have the CSS classes input input-bordered applied. But really it should be textarea textarea-bordered.

There’s no easy way for me to change that universally and globally without changing the package. Now in this case, it’s actually just a bug, and I’ve submitted a PR to the crispy-django project (it’s a 1-liner.)

However, that got me wondering how I’d now go about changing the default styling for forms, as rendered with the | crispy filter? The classes to be used in that case are provided in .../templatetagss/daisyui_field.py, but the documentation doesn’t say that those should be overridden.

Long story short, what I’d like to achieve is:

  1. Use DaisyUI for CSS everywhere
  2. Render forms with minimal effort ({{ form | crispy }} sounds best)
  3. Change the default style of some or all elements (e.g. different corner rounding, or shadows or borders…) “globally”.

Because of where the default styles are defined (in the CrispyDaisyUIFieldNode I’m not sure what the correct approach would be.

The issue here is that you’ve created a self-contradictory set of requirements.

Quoting from crispy filter — django-crispy-forms 2.0 documentation

As handy as the |crispy filter is, think of it as the built-in methods: as_table , as_ul and as_p . You cannot tune up the output. The best way to make your forms crisp is using the {% crispy %} tag with forms.

So yes, as designed and provided, you’re not going to be able to do what you want to do if you limit yourself to the crispy filter.

For the types of things that you want to do, you will need to use the crispy tag with a layout object. (That is, unless you want to create your own template pack package to provide full support to the crispy filter the way you describe.)

Got it, thanks. That makes sense regarding the crispy filter.

But using the {% crispy %} tag, I’m wondering how to avoid repeating myself every time I have a form, especially with Django’s built-in, pre-created forms (like for logins).

If you have a set of css classes that you usually want applied to a particular field type, you can create a subclass of the Field object with those classes applied.

For example, if you want certain classes applied to a textarea element, you could create a subclass like this:

class CustomTextarea(Field):
  attrs = {'class': 'some css classes to be applied'}

You would then use this object in your layout instead of Field.
Note: This does not prevent the use of the css_class attribute within the object definition - the Field.__init__ method combines that parameter with the attrs class attribute.

(There are other things that can be done as well. You can override the __init__ method of these objects to customize their initialization however you wish.)