Table of Content
- Use the right naming convention
- Follow a consistent order for model attributes and functions
- Set up Reverse Relationship Name
- Use blank and null field properties correctly
- Wrap Off
Many times I come across a Django model created by a developer, I can't; help but think about all the ways it can be improved.
There seem to be a lot of codes out there with massive technical debt.
In this post, you will learn how to improve the design of the Django Models you create.
Many of which are geared towards improving the developer experience and readability of your code.
This is a combo of recommendations from the PEP8 and Django' Coding Style.
Here are four ways you can improve your Django models:
1. Use the right naming convention
Here's a guide to follow when naming models and attributes in Django:
-
Django models are Python classes, so always use the PascalCase naming convention which requires the first word to be Capitalized. E.g.
Account
,Session
,BlogPost
, etc. -
Use snake_case for the model' attributes since they are python variables. E.g.
first_name
,last_name
, etc. -
Name your models using in the singular form e.g
Book
instead ofBooks
.This is because, in Django, a model definition is the representation of a single object.
Here, the object in this example is a book and not a collection of books.
A lot of developers tend to misunderstand this because we think of Django models in terms of the database tables.
Example of the naming conventions:
from django.db import models class Book(models.Model): title = models.CharField(max_length=50) author = models.CharField(max_length=60) publisher = models.CharField(max_length=45)
Highlighted code sample.
2. Follow a consistent order for model attributes and functions
Based on the Django Coding Style, here is how you can order a model with inner classes, methods, and attributes:
- If you defined a choice field for a given model field, define each choice as a tuple of tuples, with all letters in uppercase, as a class attribute on the model.
- All database fields
- Custom manager attributes
class Meta
def __str__()
def save()
def get_absolute_url()
- Any custom methods
Example:
from django.db import models
from django.urls import reverse
class Book(models.Model):
# CHOICES
FICTION = 'fiction'
NONFICTION = 'nonfiction'
FANTASY = 'fantasy'
Book_TYPE_CHOICES = (
(FICTION, 'fiction'),
(NONFICTION, 'nonfiction'),
(FANTASY, 'fantasy'),
)
# DATABASE FIELDS
title = models.CharField("Title", max_length=50)
author = models.CharField("Author", max_length=60)
publisher = models.CharField("Publisher", max_length=45)
book_category = models.CharField("Category", max_length=3, choices=Book_TYPE_CHOICES)
# MANAGERS
objects = models.Manager()
fiction_books = FictionManager()
# META CLASS
class Meta:
verbose_name = 'book'
verbose_name_plural = 'books'
# TO STRING METHOD
def __str__(self):
return self.title
# SAVE METHOD
def save(self, *args, **kwargs):
call_a_function()
super().save(*args, **kwargs) # Call the "real" save() method.
call_another_function()
# ABSOLUTE URL METHOD
def get_absolute_url(self):
return reverse('book_details', kwargs={'pk': self.id})
# OTHER METHODS
def all_authors(self):
call_something()
3. Set up Reverse Relationship Name
Despite being very underutilized, the related_name
attribute in the ForeignKey
fields in Django is extremely useful.
It allows you to define a meaningful name for the reverse relationship.
class Author:
name = models.CharField(max_length=60)
class Book:
title = models.CharField(max_length=50)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
That means the Author
model will have a special attribute named books
, which will return a QuerySet
with all books instances related to the author.
jk_rowling = Author.objects.get(name='J. K. Rowling')
jk_rowling.books.all()
You can also use the reverse relationship to modify the author
field on the Book
instances:
harry_potter = Book.objects.get(title='Harry Potter: New Begining')
jk_rowling = Author.objects.get(name='J. K. Rowling')
jk_rowling.books.add(harry_potter)
related_query_name
Another related name property to consider is the related_query_name. This applies related_name relations to query filters.
For example, to list all books belonging to a particular author, we can do the following:
authors = Author.objects.filter(book__title='Harry Potter')
To conventional practice, related_name
should be plural and related_query_name
should be singular.
4. Use blank and null field properties correctly
In Django, Null is database-related. It determines if a given database column will accept null values or not. Whereas Blank is validation-related. It is used during form validation when calling form.is_valid()
.
Do not use null=True
for an optional TextField. Otherwise, you will end up having two possible values for “no data,” that is None and an empty string.
Having two possible values for “no data” is redundant.
The Django convention to handle this is to use the empty string, not NULL.
Example:
# The default values of `null` and `blank` are `False`.
class Author(models.Model):
name = models.CharField(max_length=255) # Mandatory
bio = models.TextField(max_length=500, blank=True) # Optional (don't put null=True)
birth_date = models.DateField(null=True, blank=True) # Optional (here you may add null=True)
Wrap Off
Defining your models is one of the most important tasks when building an application.
Taking the time to design model fields and other aspects of your models properly makes a huge difference.
If you learned from this tutorial, or it helped you in any way, please consider sharing and subscribing to our newsletter.