One of the first things we encounter when developing a Django application is the basic database model that inherits from models.Model. Although many tutorials allow us to simply follow along, digging a little deeper into its structure and principles can help us leverage the advantages of Django ORM more effectively. In this post, we will take a detailed look at how the Django model system is structured, focusing on the inheritance structure of Django models and how to define a custom user model.


models.Model: The Base Class for All Models

In Django, all model classes inherit from models.Model. This models.Model class serves as the mapping to the database table. Each model corresponds to a database table, and the fields of the model become the columns of the table. The methods provided by this base class are key elements that enable Django ORM's core functionalities.

  • save(): Save an object to the database
  • delete(): Delete an object
  • objects.create(): Create and save an object
  • objects.filter(): Retrieve objects that meet certain conditions

By simply inheriting from models.Model, you can freely use Django's ORM features. This serves as an example of how powerfully Django ORM is designed.


AbstractUser and CustomUser: Extensible User Models

Django provides a default auth.User model, but the need to extend and customize user models is common across projects. AbstractUser is Django's abstract user model provided with this extensibility in mind. It can be used, for example, to add an email field or fields like phone number or address.

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    phone_number = models.CharField(max_length=15, blank=True)
    address = models.CharField(max_length=255, blank=True)
Django model inheritance structure

By defining CustomUser in the manner above, you can add custom fields while retaining the functionality of AbstractUser. Since AbstractUser also inherits from models.Model, you can still use the basic methods of Django ORM.


models.Manager and AbstractUserManager: Database Query and User Creation Logic

The models.Manager serves as the manager for models and provides an interface for handling queries to the database, which allows the use of methods like filter(), get(), and create() through the default manager called objects. If you need a manager specialized for a user model like CustomUser, Django provides a manager class called AbstractUserManager. This class allows you to customize the logic related to user creation.

from django.contrib.auth.models import BaseUserManager

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        # User creation logic
        pass

    def create_superuser(self, email, password=None, **extra_fields):
        # Superuser creation logic
        pass

Utilizing such managers allows for flexible responses to various scenarios that may arise during the user creation process. Since AbstractUserManager is also an extension of models.Manager, it encompasses all basic database query functionalities.


Understanding Django Model Inheritance Structure

Understanding the model inheritance structure in Django can lead to more efficient model design and implementation. In summary:

  1. models.Model: The base class for all Django models, providing ORM functionality while mapping to the database.
  2. AbstractUser: An abstract class that inherits from models.Model. By inheriting this class, you can easily define a custom user model that includes the functionalities of models.Model.
  3. AbstractUserManager: A user creation-specific manager that inherits from models.Manager. This makes it easy to customize user creation logic.

In conclusion, the model structure in Django is designed to be very flexible and powerful. When expanding user models to add custom fields, understanding and utilizing the ORM features and structure provided by AbstractUser and models.Model can lead to even more efficient and extensible database designs. By effectively leveraging this model structure in Django, developers can build complex database models with less effort.