Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check for errors and other values at the widget level - maybe using custom form field

How can I access if a field has)errors at the level of widget?

Using default I tried:

{% if widget.attributes.has_errors %} or {% if widget.has_errors %}

but are not working.

I use custom widget templates, I'm thinking to use a custom form Field and overwrite the default field.

I know clean method exist but I don't know how to push to the widget the dynamic(non default) data/attributes I want.

I tried:

class AWidget(forms.Widget):

    def get_context(self, name, value, attrs):

        context = super().get_context(name, value, attrs)
        has_errors = context['widget']['attrs'].pop('has_errors', None)
         context['widget']['has_errors'] = has_errors

It works for errors but I don't know if is the best option plus I want to pass other values/attributes from Form Field,and I think will be better to try to overwrite the Form Field but I don't know exactly how.

Also accessing individual attributes using:

 {{ widget.attrs.maxlength }} or  {{ widget.attrs.items.maxlength }}

even if accedes in a for loop works


I know I can add a parent div with a class of error:

 <div class="{% if form.field.errors %}pass_error{% endif %}">
        {{ form.field }} 
    </div>

but, that implies big changes at the css level.

I already overwrite all Django widgets with custom widgets, on error I don't need just to change a border color, but to show or not different elements of the widget template and the position of some of them change.

I already modify the based widget to add errors, but I'm looking to do it in a more elegant way at the field level by passing from the field to the widget, parameters depending on error type.

So my question is what I need to overwrite to pass from field to widget errors and other variables ?

like image 850
user3541631 Avatar asked Feb 02 '19 09:02

user3541631


1 Answers

Not sure whether this could help in your specific use case ... but just in case, please note that when you build your form in the view, you can add extra parameters as needed, then pass them down to your custom widget.

Working example:

file "forms.py"

from django import forms


def build_ingredient_form(unit):
    """
    Ingredient form factory

    Here we build the form class dynamically, in order to acces 'unit' via closure.
    References:
        http://stackoverflow.com/questions/622982/django-passing-custom-form-parameters-to-formset#623030
    """
    class IngredientForm(forms.Form):
        #quantity = forms.DecimalField(max_digits=10)
        quantity = UnitField(unit, required=False)
        ...
    return IngredientForm


file "fields.py"

from django import forms
from .fields import UnitField


class UnitField(forms.CharField):
    """
    Custom field to support UnitWidget

    References:
        - http://tothinkornottothink.com/post/10815277049/django-forms-i-custom-fields-and-widgets-in
    """

    def __init__(self, unit, *args, **kwargs):
        self.unit = unit
        super(UnitField, self).__init__(*args, **kwargs)
        self.widget = UnitWidget(unit)

    ...

file "widgets.py"

from django import forms
from .models import Unit


class UnitWidget(forms.TextInput):

    def __init__(self, unit, attrs=None):
        if unit is None:
            self.unit = Unit()
        else:
            self.unit = unit

    ...

like image 95
Mario Orlandi Avatar answered Sep 30 '22 06:09

Mario Orlandi