In this tutorial we are going to focus on Form.clean() method and clean_fieldname() method , these methods help us validate data entered in forms by users.
we are going to use this app https://github.com/felix13/djangoclean for us to understand better.
lets say we have an app that takes in student information , for example, first name , last name and an image of the student.
We also want to validate the data entered by students and after thinking about it, we settle on the following rules.
- No student can have the same name as first name and last name, for example if you enter your first name as " Felix " and last name as " Felix " our app will throw an error.
- We are going to allow students to upload images that have the following extensions only (
'jpeg') and anything else will throw an error.
so if a user uploads a video with an extension of lets say
.mp4 our app should reject it.
I know we have people with the same name as first name and last name, this is just for demonstration purposes.
Now lets lets dive into code and see how our app will look like, we will start with
from django.db import models class Document(models.Model): first_name = models.CharField(max_length=255, blank=True) last_name = models.CharField(max_length=255, blank=True) image = models.FileField(upload_to='images/') uploaded_at = models.DateTimeField(auto_now_add=True)
In the above code we have a
Document model which has fields for first_name, last_name, image and uploaded_at , Each attribute of the model represents a database field.
Lets look at our
forms.py file , it will look like this
class DocumentForm(forms.ModelForm): class Meta: model = Document fields = ('first_name', 'last_name', 'image', ) def clean_image(self): IMAGE_FILE_TYPES = ['png', 'jpg', 'jpeg'] uploaded_image = self.cleaned_data.get("image", False) extension = str(uploaded_image).split('.')[-1] file_type = extension.lower() if not uploaded_image: raise ValidationError("please upload an Image") # handle empty image if file_type not in IMAGE_FILE_TYPES: raise ValidationError("File is not image.") return uploaded_image def clean(self): cleaned_data = super().clean() first_name = cleaned_data.get('first_name') last_name = cleaned_data.get('last_name') if first_name == last_name: raise ValidationError( "First name and last name cannot be the same." )
Let me explain what is going on in our
forms.py file, first of all , we have two methods which are
You might be asking yourself , why is our method called
clean_image() ? , in Django, they generally call this method
<fieldname> is replaced with the name of the form field attribute .
In our example since we want to clean a specific field which is the
image field, we will replace the
image making it
Our method here does two things
- Check if image is uploaded, if not raise validation error.
- Check if image extension is of the type that is allowed
'jpeg') , if not raise validation error.
This is the form's
clean() method , do not confuse it with
clean() method on a field that we did above.
Django docs says
It’s important to keep the field and form difference clear when working out where to validate things. Fields are single data points, forms are a collection of fields.
read more on this here
This method is used in cleaning and validating fields that depend on each other. In our case we are checking if
first_name == last_name , if equal then we raise validation error.
This is validation that is specific , we did write a clean method that operates on the image field.
Used in performing validation on more than one field at a time, In our example we did comparison of two fields by checking if
first_name == last_name .
You can find the source code of the app used in this example here
photo by Kari Shea on unsplash
- Which Companies Use Django
- What to do when Django's static files are not working
- What is super() in python