skip to Main Content

I’m using Django 4.2.9 and need a form add an additional class to an input field, in case the validiation failed.

I can already add classes for every case, but I do not know how to do it for the error-case.

class ItemForm(forms.models.ModelForm):
    class Meta:
        model = Item
        fields = ("text", )
        widgets = {
            "text": forms.widgets.TextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}

    def save(self, for_list):
        self.instance.list = for_list
        return super().save()

I’d like to have class="form-control form-control-lg is-invalid" for the text-input.

<form method="POST" action="/lists/8/">
    <input type="text" name="text" value="Buy wellies" placeholder="Enter a to-do item" class="form-control form-control-lg" required id="id_text">
    <input type="hidden" name="csrfmiddlewaretoken" value="vcojkMtz3GeonURczjMwIsbsDPQUbeKgrXrPIxZY4jIJSfuUKKGVgaj7wLQBatsd">                        
    <div class="invalid-feedback"><ul class="errorlist"><li>You've already got this in your list</li></ul></div>
                        
</form>

2

Answers


  1. I would probably in your case when validation fails over ride the init in the following way:

    class ItemForm(forms.models.ModelForm):

    class Meta:
        model = Item
        fields = ("text",)
        widgets = {
            "text": forms.widgets.TextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}
    
    def __init__(self, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        if self.errors and 'text' in self.errors:
            text_widget = self.fields['text'].widget
            existing_classes = text_widget.attrs.get('class', '')
            text_widget.attrs['class'] = f'{existing_classes} is-invalid'
    
    def save(self, for_list):
        self.instance.list = for_list
        return super().save()
    

    This way we add "is-invalid" class on the text input when validation fails. So basically and hopefully this code will check for any erros in the form text fields. If there is we will be "is-invalid"

    I think a better approach (I like everything in parts) is to put the error classes in separate methods so depending what else your project does you might reuse them going forward.

    Good luck 🙂

    Login or Signup to reply.
  2. This kind of job must be done in _post_clean method not init. Cause you initiate the form. First Time without args ItemForm(), and after post request ItemForm(request.POST). When you use in your view :

    if request.method == "POST":
       myform = ItemForm(request.POST)
       if myform.is_valid():
            [...]
    

    With is valid your form will run full_clean. After fields cleaning will be run _post_clean that you can override :

    class Meta:
        model = Item
        fields = ("text",)
        widgets = {
            "text":  forms.widgets.TextInput(
                attrs={
                    "placeholder": "Enter a to-do item",
                    "class": "form-control form-control-lg",
                }
            ),
        }
        error_messages = {"text": {"required": EMPTY_ITEM_ERROR}}
    
    def save(self, for_list):
        self.instance.list = for_list
        return super().save()
    
    def clean_text(self):
        [Here your cleaning  field method]
    
    def _post_clean(self):
        super()._post_clean()
        for k,v in self.errors.items():
            self.fields[k].widget.attrs['class'] += 'is-invalid'
        #in This form you Can directly write : self.field['text'].widget.attrs['class'] += 'is-invalid'
    

    For more détails of validation :
    https://docs.djangoproject.com/en/5.0/ref/forms/validation/

    Hope it will help you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search