4 Ways on How to Improve Your Django Models

Here are four ways you can improve your Django models

Picture of Nsikak Imoh, author of Macsika Blog
White background with the text 4 Ways on How to Improve Your Django Models
White background with the text 4 Ways on How to Improve Your Django Models

This post is part of the tutorial series titled Learn to Use Django with FastAPI Frameworks


Table of Content

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 of Books.

    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:

  1. 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.
  2. All database fields
  3. Custom manager attributes
  4. class Meta
  5. def __str__()
  6. def save()
  7. def get_absolute_url()
  8. 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()
Highlighted code sample.

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')
Highlighted code sample.

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()
Highlighted code sample.

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)
Highlighted code sample.

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')
Highlighted code sample.

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)
Highlighted code sample.

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.

Get the Complete Code of Django and FastAPI Combo Tutorials on Github.

Connect with me.

Need an engineer on your team to grease an idea, build a great product, grow a business or just sip tea and share a laugh?