Models are the foundation of any Django project. Django web applications use models to access and manage data from the database. But rushing to write models without devoting time to think about the important design decisions can hurt after months or years to come.
In this article, we’ll be learning about the basics of Django models and also the best practices to make the most out of them.
Prerequisites:
This article requires prior knowledge of the Django web framework and is meant for developers with beginner knowledge.
What are Django Models?
A model is a class that represents a table or a collection in our database, with each attribute representing a table or a collection field. Models are defined inside a Django app in a models.py
file.
Models determine the structure of stored data, including field types and optionally their maximum size, default values, selection list options, documentation help text, form label text, and so on. The model is defined independently of the underlying database.
You don't need to talk to the database directly once you've decided which one to use — all you have to do now is write your model structure and other code, and Django will handle the job of talking to the database for you.
How to Create a Model?
Before diving in and starting to code the models, take a few minutes to consider what data you need to store and the relationships between the various objects. Here is the basic Django syntax to define a model:
from django.db import models
class Demo(models.Model):
email = models.CharField(max_length = 50)
user_name = models.CharField(max_length = 50)
phone_number = models.IntegerField()
class Meta:
db_table = "demo"
Every model inherits from django.db
, and the Meta
class's db_table
field allows us to specify the database's actual table or collection name.
After you have defined your model, you will need to run the following command to tell Django to generate the table in the actual database:
python manage.py makemigrations
python manage.py migrate
Read more about Django Models in the official Django Documentation.
Best Practices for Django Models:
Here are some of the best practices to keep in mind while designing your models:
- Keep no more than 5-10 models per Django app. The more models in an app, the messier the code is bound to get.
- Django has defined a standard coding style to keep in mind while writing your models. It recommends the following ordering of the model fields:
- choices
- database fields
- custom manager attributes
Meta
def __str__()
def save()
def get_absolute_url()
- custom methods
- Always use singular nouns for model naming, for example, User, Post, Article, and so on as a model defines the properties of an object.
- Avoid using multi-table inheritance since it causes a lot of confusion and adds a lot of overhead.
- Use explicit
OneToOneFields
andForeignKeys
between models instead of multi-table inheritance to regulate when joins are traversed. - Use a
OneToOneField
instead of usingForeignKey
withunique=True
. - For
BooleanField
, do not usenull=True
orblank=True
. It's also worth noting that it's preferable to set default values for such fields. UseNullBooleanField
if required in case you realize that the field can remain empty. - Using model
help_text
in fields as a part of the documentation to help other developers understand more about the data structure. - Use
Abstract
Base Class when you want to put some common information into many other models. It is very simple - write in your base class and putabstract = True
in theMeta
Class. - Use
str
method in the non-abstract models to return a distinguishable name for your Django models. - Create a
TimeStampedModel
for your Django project where you require to include a created and modified timestamp field on almost all of your models. It could look something like this.
from django.db import models
class TimeStampedModel(models.Model):
"""
An abstract base class model that provides self-updating created and modified fields.
"""
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
-
Don’t use
null=True
andblank=True
if you don’t need them. Their use cases can often be confusing. Consider the following:-
null=True
allows the column to keep a null value. -
blank=True
is used only in Forms for validation and is not related to the database.
-
However, for
TextField
, it’s always safe to define a default value such as an empty string.
Well, there could be cases where a careful design won’t be enough, you’ll have to take precautions while deployment and management of Django migrations that help you manage your models and the underlying database. Below are some of the points to keep in mind when you’re moving ahead with migrating the models:
- Always back up the existing data before running a migration. Also, if huge data is at risk (think thousands of rows in a table), make sure to run extensive tests on a staging server before taking it live on the production server.
- Always put your migration file in version control. It is an absolute necessity to enable code collaboration and consistency during development.
- Try to avoid generic relations and
GenericForeignKey
as they could cause a reduction in the speed of queries due to a lack of indexing between models. Moreover, there are chances of data corruption as a table can refer to another against a non-existent record.
Conclusion
Models are the foundation of any Django project and thus, they should be designed and deployed after careful thinking. In this article, we have learned what are models in Django, how to create them and the best practices to keep in mind to prevent future bottlenecks and build an efficient application.
That’s all for this article. In case you want to connect with me, follow the links below:
Top comments (4)
Hi Pragati, thanks for sharing this :)
FYI we've added your blog post into a GitHub project gathering content about best coding practices :)
github.com/promyze/best-coding-pra...
Thank you so much Cédric :D
Can you please explain this point using example "Avoid using multi-table inheritance since it causes a lot of confusion and adds a lot of overhead."
Sure.
So, multi-table inheritance allows you to create a new model that inherits fields from another model, which is implemented by creating a new table in the database for the child model. While this feature can be useful in some cases, it can also cause confusion and add overhead to Django models.
One issue with multi-table inheritance is that it can make querying and updating data more complex. Since each child model has its own table, querying or updating data across multiple tables requires using complex JOIN statements. This can make code harder to read and slower to execute.
Another issue with multi-table inheritance is that it can lead to redundant data being stored in the database. Each child model has its own table, which means that any fields inherited from the parent model are duplicated in each child table. This can lead to larger and less efficient databases, as well as increased storage costs.
Furthermore, multi-table inheritance can make it harder to maintain and evolve your database schema over time. Adding new fields or modifying existing ones in the parent model can require updating each child model and table, which can be time-consuming and error-prone.