Question

So I want to use this getattribute function (found on this link) https://snipt.net/Fotinakis/django-template-tag-for-dynamic-attribute-lookups/

in my django templates. I created a templatetags folder in my app folder where my models.py is. I also created and saved an empty inint.py file in the templatetags folder. I then created a file called getattribute.py in the template tags folder and copy-pasted the snippet found in the link above into the getattribute.py file and saved the file.

This is what my template looks like:

<html>
    <body>
        <form method="post" action="">{% csrf_token %}
            {{ form.first_name }} {{form.last_name }} <br>
            {{ form.username }} {{ form.password }} <br>
            <input type="submit" value="Register"/>
        </form>

{% load getattribute %}

{% for field, error in form.errors.items %}
    {% if forloop.counter == 1 %}
        {% with field_obj=form|getattribute:field %}
            {{ field_obj.label }}{{ error | striptags }}
        {% endwith %}
    {% endif %}
{% endfor %}
</body>
</html>

This is how my models.py looks.

class Users(models.Model):
    alpha_field = RegexValidator(regex=r'^[a-zA-Z]+$', message='Name can only contain letters')
    user_id = models.AutoField(unique=True, primary_key=True)
    username = models.SlugField(max_length=50, unique=True)
    first_name = models.CharField(max_length=50, verbose_name='first Name', validators=[alpha_field])
    last_name = models.CharField(max_length=50, validators=[alpha_field])
    password = models.SlugField(max_length=50)

My forms.py is this.

class UsersForm(forms.ModelForm):

    class Meta:
        model = Users
        widgets = {'password':forms.PasswordInput()}

    def __init__(self, *args, **kwargs):
        super( UsersForm, self ).__init__(*args, **kwargs)
        self.fields[ 'username' ].widget.attrs[ 'placeholder' ]="Username"
        self.fields[ 'first_name' ].widget.attrs[ 'placeholder' ]="First Name"  
        self.fields[ 'last_name' ].widget.attrs[ 'placeholder' ]="Last Name"
        self.fields[ 'password' ].widget.attrs[ 'placeholder' ]="Password"
        self.fields['first_name'].label='first Name'

and this is my views.py

def home_page(request):
    form = UsersForm()
    if request.method == "POST":
        form = UsersForm(request.POST)

        if form.is_valid():
            form.save()
    c = {}
    c.update(csrf(request))
    c.update({'form':form})
    return render_to_response('home_page.html', c)

Now, when I run the server, the form is displayed with no errors. However, if I purposely not fill out the first name section and hit submit, it says "This field is required." I want it to say the verbose name and the snippet is supposed to make it say the verbose name if, in my template, I use {{ field_obj.label }}, right? But it is not display the verbose name for some reason. I'm guessing it is because I'm not using the templatetags properly?

Was it helpful?

Solution

In your form, it may help to have a clean method:

def clean(self):
    first_name = self.cleaned_data.get('first_name')

    if password is None:
        raise forms.ValidationError('This is a custom error message.')

    return self.cleaned_data

Then, in your template, you can have code like:

    {{ form.first_name }}
    {% if form.first_name.errors %}
        &nbsp;{{form.first_name.errors.as_text}}
    {% endif %}

Otherwise, django's default form validation will treat all your inputs as required, and provide that generic message.

Another option, from the docs, is to define error messages at the form field level: https://docs.djangoproject.com/en/dev/ref/forms/fields/

name = forms.CharField(error_messages={'required': 'Please enter your name'})

This will add the custom error message based on the error type, so in your case, you could use something like:

first_name = models.CharField(max_length=50, verbose_name='first Name', validators=[alpha_field], error_messages={'required': 'Please enter a first name'})
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top