python – How do I do model-based form validation in Django?

Question:

Hello everyone! I just started to master Django, a question arose about form validation, based on a model, it is not entirely clear how to do it, because form.is_valid() checks the form already for all fields, but I would like a custom validation, according to certain conditions:

I created a model:

models.py

from django.db import models
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator


class Feedback(models.Model):
    name = models.CharField(max_length=25,verbose_name="Имя",validators=[
        RegexValidator(
            regex='^[a-z]*$',
            message='Username must be Alphanumeric',
            code='invalid_username'
        ),
    ])
    email = models.EmailField()
    phone = models.CharField(max_length=12,verbose_name="Телефон")
    text = models.TextField(max_length=128)
    date = models.DateTimeField(auto_now_add=True,verbose_name="Дата")

    def __str__(self):
        return "Новый вопрос: %s %s" % (self.name, self.phone)

    class Meta:
        verbose_name = 'Вопросы клиентов'
        verbose_name_plural = 'Обратная связь'

Based on the model, I created a form:

forms.py

from django import forms
from django.forms import ModelForm
from .models import *


class FeedbackForm(forms.ModelForm):
    class Meta:
        model = Feedback
        exclude = ['date']

    widgets = {
        'name':forms.TextInput(attrs={'class':'fb_form','placeholder':'Ваше имя'}),
        'email':forms.TextInput(attrs={'class':'fb_form','placeholder':'E-mail адрес'}),
        'phone':forms.TextInput(attrs={'class':'fb_form','placeholder':'Контактный телефон'}),
        'text': forms.Textarea(attrs={'class':'fb_form','placeholder':'Ваше сообщение','rows':20, 'cols':40})
    }

And the view itself:

views.py

def feedback(request):
    form = FeedbackForm(request.POST or None)

    if request.method == "POST" and form.is_valid():
        name = form.cleaned_data['name']
        email = form.cleaned_data['email']
        phone = form.cleaned_data['phone']
        text = form.cleaned_data['text']

        try:
            send_mail(name,text+'\n'+email+'\n'+phone,'test@yandex.ru',['test@yandex.ru'], fail_silently=False)
            new_form = form.save()
            return HttpResponse('yes :)') 
        except BadHeaderError:
            return HttpResponse('Invalid header found')
    else:
        form = FeedbackForm()

    return render(request, 'feedback/feedback.html', locals())

If you create entries from the admin RegexValidator , then the validation through the RegexValidator works out, if you enter an incorrect character, you immediately see a notification.

How to do custom model-based form validation so that the result is visible on the web page?

There are many examples in the internet where validation is done immediately in forms.py , not based on a model, without it it turns out to set your own verification conditions, but with a model – I don’t understand how.

Can you give an example of how it should be?

Answer:

Models also have field validation , for example the clean() or clean_fields() method.

An example from the documentation:

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
Scroll to Top