Django Models: Basics and Best Practices
Tags: beginners, django, python, webdev
Published: 2022-04-15 04:22:46

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](https://docs.djangoproject.com/en/4.0/topics/db/models/) 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:

```py
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](https://docs.djangoproject.com/en/4.0/topics/db/models/).

## 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](https://docs.djangoproject.com/en/4.0/internals/contributing/writing-code/coding-style/#model-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` and `ForeignKeys` between models instead of multi-table inheritance to regulate when joins are traversed.
- Use a `OneToOneField` instead of using `ForeignKey` with `unique=True`.
- For `BooleanField`, do not use `null=True` or `blank=True`. It's also worth noting that it's preferable to set default values for such fields. Use `NullBooleanField` 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 put `abstract = True` in the `Meta` 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.

```py 
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` and `blank=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:

[LinkedIn](https://www.linkedin.com/in/pragativerma18/) | [GitHub](https://github.com/PragatiVerma18/) | [Twitter](https://twitter.com/pragati_verma18) | [Medium](https://medium.com/@itispragativerma)