GSOC 2021 Proposal - Form Styles as Objects

Hey all, my name is Lewis. I’m a penultimate-year MSci Computer Science student at the University of Exeter.

About me

As a quick brief on my experience, I’ve been using Django professionally for over 12 months. These projects include:

  • An EdTech platform, under Magpie Education (Django + Angular, monolithic).
  • A Virtual Learning Environment application, under Hatless Studios (Django + Vue, backend-for-frontends over DRF).

In the past, I’ve used the framework for a variety of hackathons and personal projects. This includes:

  • Bunchup, a social media platform for building online communities (github/LloydTao/Hackathon-NASA-2020).
  • A tropical cyclone visualiser (github/LloydTao/Hackathon-Met-Office-2020).

Finally, although it’s not much of a mark, I do have one OSS contribution under my belt:

  • nuxt/create-nuxt-app: feat: prompt for git (github/nuxt/create-nuxt-app/pull/596).

Issue

In my opinion, it’s too difficult to inject CSS classes and styles into form fields.

Let’s explore a use case. Currently, we’re able to address a field’s attributes within a form. For example, we can use {{ field.field }} in an email field in order to render <input id="id_email" type="email"> in the markup.

However, there’s no direct way to inject classes and styles here. In Bootstrap, a simple class="form-control" takes an <input> from ugly to pretty, but doing this is difficult.

It would be nice to have a simple method of applying the form-control class, and any other classes and styles.

Current alternatives

One solution is to write CSS for <input> and related tags.

However, this isn’t a modular approach. Additionally, utility-first CSS frameworks (e.g. TailwindCSS) would be left in the dust, requiring a wealth of @apply rules that defeat utility-first practises.

Another way to get around this is to use the third-party package django-crispy-forms.

However, I believe that a feature as simple as adding a CSS class to a field should not require third-party packages. I propose that DCF still be used for fully controlling of the rendered HTML, while Django implements simple class and style injection.

Proposed task

I would like to build a FormStyle feature.

The purpose is to allow developers to easily add a string to represent the class or style attributes of a field’s attributes within the form.

As a proof of concept, this snippet represents what a develop would write:

from django.contrib import forms

class UserFormStyle(forms.FormStyle):

    classes = {
        "label": "form-check-label",
        "input": {
            "checkbox": "form-check-input",
            "email": "form-control",
            "password": "form-control",
            "text": "form-control",
        },
        "button": {
            "submit": "btn btn-primary",
        },
    }
	
	styles = ...

It would then be used within a form through:

class BookForm(forms.Form):

    ...
    
    class Meta:
        model = User
        fields = ["username", "email", "password", "newsletter"]
        style = UserFormStyle

Upon render, Django will then inject these strings into the field’s attributes.

For example, instead of <input id="id_email" type="email">, Django will now render <input id="id_email" type="email" class="form-control">.

Where no string exists, Django will not add any class="..." or style="..." attributes to the markup.

Acceptance criteria

As a user, I should be able to:

  • Create a FormStyle object within a Django app.
  • Use the FormStyle within a Form’s meta attributes.
  • Successfully render a form with the respective FormStyle strings.
  • Read documentation on the use and purpose of FormStyles.
  • Grab an example FormStyle from the documentation to easily edit and implement.

Schedule

My summer working hours are very flexible.

I’ll be on break from my degree over summer, with my only current commitment being a zero-hour software engineering contract.

Final notes

If this is not a project worth undertaking, I’m super happy to work on anything else under the Django foundation mentorship. This looks to be an incredible opportunity.

Just let me know, and I’ll explore other options, dig into the requirements, and create another proposal.

1 Like

Hi @LloydTao — Thanks for posting.

I’m going to say that this is the exact kind of proposal that we’d say would belong in a third-party package, and then given that I’d say, well what about crispy forms, which targets this kind of use case.

There’s also a current PR to switch form rendering to the template engine, which is on the long-list for Django 4.0, and should alter the landscape here somewhat.

As such, I have to say this probably isn’t a good proposal for GSoC this year.

Kind Regards,

Carlton