SoFunction
Updated on 2025-04-13

Detailed explanation of ORM in Django (Latest recommendation)

Django's ORM (Object-Relational Mapping) is a database abstraction layer provided by the Django framework, allowing developers to use Python code to operate databases without directly writing SQL statements. It provides an efficient and intuitive way to manage database models and query data.

1 ORM introduction

1.1 ORM concept

Object Relational Mapping (ORM) pattern is a technology to solve the phenomenon of mismatch between object-oriented and relational databases.

Simply put, ORM automatically persists objects in the program into a relational database by using metadata that describes the mapping between the object and the database.

ORM acts as a bridge between the business logic layer and the database layer.

1.2 Origin of ORM

Let's start with O/R. The letter O originates from "Object", while R originates from "Relational".

Objects and relational databases are involved in almost all software development processes. At the user level and business logic level, we are object-oriented. When the object's information changes, we need to save the object's information in a relational database.

When developing in the previous way, programmers will include many SQL statements in their business logic code to add, read, modify, and delete related data, and these codes are usually repeated.

1.3 ORM's Advantages and Disadvantages

Advantages of 1.3.1ORM

The main problem that ORM solves is the mapping of objects and relationships. It usually corresponds to a class and a table one by one, each instance of the class corresponds to a record in the table, and each property of the class corresponds to each field in the table.

ORM provides mapping to databases, without writing SQL code directly, just manipulating data from the database like an operation object.

Let software developers focus on the processing of business logic, improving development efficiency.

1.3.2 Disadvantages of ORM

The disadvantage of ORM is that it will sacrifice the execution efficiency of the program to a certain extent.

If ORM uses too many SQL statements, it will not be written, and the related skills of relational databases will be degraded...

1.4 ORM summary

ORM is just a tool, and tools can really solve some repetitive, simple labor. This is undeniable.

But we cannot expect a tool to solve all problems once and for all, and some special problems still need to be handled specially.

However, there should be very few cases in the entire software development process that require special treatment, otherwise the so-called tool will lose its meaning of existence.

2 Common fields for Django models

2.1 Common fields for Django models

from  import models
class ForeignKey():
    pass
class ForeignMany():
    pass
class Event():
    # int autoincrement column, the parameter primary_key=True must be filled in.  When no primary key is specified in the model, django will automatically create a column with the column name id as the primary key.    a = (primary_key=True)  # Primary key    # The most commonly used field must specify the max_length character length    b = (max_length=24, null=False)  # Project Name    # There is a difference between Boolean and NullBooleanField, True/False, this type does not allow null.    c = (default=True)  # Is it valid    # Can be null boolean    d = (default=True)  # Whether to display    # json type    e = ()  # Event details    # UUID
    f = ()
    # Small integer - 32768 ~ 32767    g = ()
    # Positive small integer 0 ~ 32767    h = ()
    # integer sequence (signed) -2147483648 ~ 2147483647    i = ()
    # Positive integer 0 ~ 2147483647    j = ()
    # Long integer (signed) -9223372036854775808 ~ 9223372036854775807    k = ()
    # Long integer, time interval, stored in the database according to bigint, the value obtained in the ORM is of type    l = ()
    #Floating point type    m = ()
    # Amount type->100.12    n = (max_digits=5, decimal_places=2)
    # Binary type    o = ()
    # One to Many    p = (to=ForeignKey,  # Related to the table                          to_field='project_id',  # The field of the associated table can be associated with the primary key of the associated table without specifying it.                          db_constraint=False,  # Whether to generate foreign key constraints (default is True)                          related_name="_project_id",  # Reverse query name                          on_delete=,  # Associate Delete Options                          db_column='project_id',  # Set the name in the table                          help_text='project_id associated to Event table',  # Description field will be displayed in the admin background and will not be synchronized to the database                          )
    # One-to-one, and one-to-many systems, only by default unique=True is added    q = (to=ForeignKey,  # Related to the table                             to_field='project_id',  # The field of the associated table can be associated with the primary key of the associated table without specifying it.                             db_constraint=False,  # Whether to generate foreign key constraints (default is True)                             related_name="_project_id",  # Reverse query name                             on_delete=,  # Associate Delete Options                             db_column='project_id',  # Set the name in the table                             help_text='project_id associated to Event table',  # Description field will be displayed in the admin background and will not be synchronized to the database                             )
    # Many to many    # Create a third table manually. Although you can use orm's query method, add(), set(), remove(), and clear() are not supported.    r = (to='ForeignKey',  # Related to that table, that is, associated with that table                               through='ForeignMany',  # Customize the third table, you can automatically generate the third table without setting it.                               through_fields=('book', 'author')  # Customize the two fields in the third table to manage the main table and the associated table without setting                               )
    # Create time, when creating data records, the current time will be added to the database.    s = (auto_now_add=True)
    # Modify time, this field will be updated every time the data record is updated.    t = (auto_now=True)
class Meta:
    # The default table name of the model in the database is APP name_class name, and the default value can be re-defaulted through db_table, which is equivalent to the indication of the specified model in the database.    db_table = 'project_event'

2.2 Django models field parameters null

Used to indicate that a field can be empty.

unique

If set to unique=True, the field must be unique in this table.

db_index

If db_index=True it means setting the database index for this field.

default

Set default values ​​for this field.

auto_now_add

The time field is unique. The three time fields DatetimeField, DateField, and TimeField can all be set as follows.

Configure auto_now_add=True, and the current time will be added to the database when creating data records.

auto_now

The time field is unique. The three time fields DatetimeField, DateField, and TimeField can all be set as follows.

Configure auto_now=True, and this field will be updated every time the data record is updated.

2.3 Django models relational fields

2.3.1 ForeignKey

Foreign key types are used in ORM to represent foreign key association relationships. Generally, the ForeignKey field is set to the 'many' side of 'one-to-many'.

ForeignKey can be associated with other tables and can also be associated with itself.

Field parameters

to

Set the table to be associated

to_field

Set the fields of the table to be associated

related_name

The field name used in reverse operation is used instead of the 'table name_set' in the original reverse query.

For example:

class Classes():
    name = (max_length=32)
class Student():
    name = (max_length=32)
    theclass = (to="Classes")

When we want to query all students associated with a class (reverse query), we will write this:

().student_set.all()

When we add the parameter related_name in the ForeignKey field,

class Student():
    name = (max_length=32)
    theclass = (to="Classes", related_name="students")

When we want to query all students associated with a class (reverse query), we will write this:

().()

related_query_name

The join prefix used during reverse query operation is used to replace the table name.

on_delete

When data in an associated table is deleted, the behavior of the rows associated with the current table.

parameter operate
Delete associated data, and delete associated with it
models.DO_NOTHING Delete associated data, raise an error IntegrityError
Delete the associated data, raise an error ProtectedError
models.SET_NULL Delete the associated data, and set the associated value to null (presumably the FK field needs to be set to nullable)
models.SET_DEFAULT Delete the associated data and set the associated value to the default value (presumably, the default value needs to be set in the FK field)
Delete associated data,
a. The associated value is set to the specified value, set: (value)
b. The associated value is set to the return value of the executable object, set: (func():return 10)

db_constraint

Whether to create a foreign key constraint in the database, default to True.

2.3.2 OneToOneField

One-to-one field.

Usually one-to-one fields are used to extend existing fields.

One-to-one relationships are often used when the query frequency gap between different fields of a table is too large, the fields that could have been stored in a table are split and opened in two tables, and then the two tables are established with one-to-one relationships.

Field parameters

to

Set the table to be associated.

to_field

Set the fields to be associated.

on_delete

Same as ForeignKey field.

2.3.3 ManyToManyField

Used to represent a many-to-many relationship. Establish an association relationship in the database through the third table.

Field parameters

to

Set the table to be associated

related_name

Same as ForeignKey field.

related_query_name

Same as ForeignKey field.

symmetrical

Only used when many-to-many autocorrelation, fields specify whether to create a reverse operation internally. Default is True.

For example:

class Person():
    name = (max_length=16)
    friends = ("self")

At this time, the person object does not have a person_set attribute.

class Person():
    name = (max_length=16)
    friends = ("self", symmetrical=False)

At this point, the person object can now use the person_set attribute for reverse query.

through

When using the ManyToManyField field, Django will automatically generate a table to manage many-to-many relationships.

But we can also manually create a third table to manage many-to-many relationships. At this time, we need to specify the table name of the third table through.

through_fields

Sets the associated field.

db_table

When the third table is created by default, the name of the table in the database.

Three ways to have many-to-many relationships

Method 1: Create the third table by yourself

class Book():
    title = (max_length=32, verbose_name="Book Title")
class Author():
    name = (max_length=32, verbose_name="Author's Name")
# Create the third table by yourself, and associate the book and the author through foreign keys respectivelyclass Author2Book():
    author = (to="Author")
    book = (to="Book")
    class Meta:
        unique_together = ("author", "book")

2. Method 2: Automatically create the third table through ManyToManyField

class Book():
    title = (max_length=32, verbose_name="Book Title")
# Automatically create a third table through the ManyToManyField built into ORMclass Author():
    name = (max_length=32, verbose_name="Author's Name")
    books = (to="Book", related_name="authors")

3. Method 3: Set ManyTomanyField and specify the third table you create

class Book():
    title = (max_length=32, verbose_name="Book Title")
# Create the third table yourself and specify the association through ManyToManyFieldclass Author():
    name = (max_length=32, verbose_name="Author's Name")
    books = (to="Book", through="Author2Book", through_fields=("author", "book"))
    # through_fields accepts a 2 tuple ('field1', 'field2'):    # where field1 is the author of the foreign key of the model that defines ManyToManyField, and field2 is the foreign key name of the associated target model (book).class Author2Book():
    author = (to="Author")
    book = (to="Book")
    class Meta:
        unique_together = ("author", "book")

Notice:

When we need to store additional fields in the third relation table, we need to use the third method.

However, when we use the third method to create a many-to-many relationship, we cannot use the set, add, remove, and clear methods to manage many-to-many relationships. We need to use the model of the third table to manage many-to-many relationships.

2.4 Meta Information

The corresponding class of ORM contains another Meta class, and the Meta class encapsulates some database information. The main fields are as follows:

class Meta:
    #app_label declaration belongs to which application    app_label='Grade_manager'
    #table_name Custom table name, if the table name is not specified, it will be: Application name_Class name    db_table='grade'
    #Some databases have database tablespaces, such as Oracle.  You can use db_tablespace to specify which database table space the corresponding database table of this model is placed in.    db_tablespace = "user"
    #DateField or DateTimeField fields names. If this option is provided, the module will have a get_latest() function to get the "latest" object (based on that field): get the last order_date field record,    get_latest_by = "order_date"   
    #Give this model a simpler and easier to read    verbose_name = "pizza"        
    What is the plural form of the # model    verbose_name_plural
    # Joint Index    index_together=("grade","user")
    # Specify the default field sorting. Only when this property is set can the result we query be reverse().    ordering="grade"

2.5 Difference between blank and null

  • blank

When set to True, the field can be empty. When set to False, fields must be filled in. The character fields CharField and TextField use empty strings to store empty values.
If True, the field is allowed to be empty and is not allowed by default.

  • null

When set to True, django uses Null to store null values. Date, time, and numeric fields do not accept empty strings. So when setting IntegerField, the DateTimeField field can be empty,
Blank and null need to be set to True.
If True, the null value will be stored as NULL, defaulting to False.

If you want to set BooleanField to empty, you can choose NullBooleanField field.

In summary, null is for the database. If null=True, it means that the field of the database can be empty. blank is for the form. If blank=True, it means that you can not fill in the field when filling in your form, for example, when adding a model record to the admin interface. Intuitively, this field is not bold

2.6 Comparison of Django models field with mysql field

django field mysql field Prepare
AutoField integer AUTO_INCREMENT The primary key is automatically added, provided by Django Model by default and can be rewritten.
BigAutoField bigint AUTO_INCREMENT
BooleanField tinyint(1) Boolean type field, usually used to record status tags.
BinaryField longblob
CharField varchar(%(max_length)s)
CommaSeparatedIntegerField varchar(%(max_length)s)
DecimalField numeric((max_digits)s , %(decimal_places)s) Consider using it when developing businesses that require high data accuracy.
(max_length=8, decimal_places=2)
It is to define a number with a length of 8 bits and a precision of 2 bits, such as the number: 666666.66
IntergerField int(11) Like AutoField, the only difference is that it does not increase itself.
PositiveIntegerField int(11) The same as IntegerField, only contains positive integers.
SmallIntegerField smallint Small integers are usually used.
CommaSeparatedIntegerField varchar(%(max_length)s)
DateField date
DateTimeField datetime
DurationField bigint
FileField varchar(%(max_length)s)
FilePathField varchar(%(max_length)s)
FloatField double precision
IntegerField integer
BigIntegerField bigint
IPAddressField char(15)
GenericIPAddressField char(39)
NullBooleanField bool
OneToOneField integer
PositiveIntegerField integer UNSIGNED
PositiveSmallIntegerField smallint UNSIGNED
SlugField varchar(%(max_length)s)
SmallIntegerField smallint
TextField longtext
TimeField time
UUIDField char(32)

2.7 Django models fields and Sql statements

The following example defines aPersonModel, includingfirst_nameandlast_name

from  import models
class Person():
    first_name = (max_length=30)
    last_name = (max_length=30)

first_nameandlast_nameis a field of the model. Each field is specified as a class attribute, each attribute maps to a database column.

The abovePersonThe model will create a database table like this:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

Some instructions:

  • The name of the table myapp_person is automatically generated. If you want to customize the table name, you need to specify the db_table parameter in the model's Meta class. It is strongly recommended to use lowercase table names, especially when using MySQL as the backend database.
  • The id field is automatically added. If you want to specify a custom primary key, just specify primary_key=True in one of the fields. If Django finds that you have explicitly set Field.primary_key, it will not add the automatic ID column.
  • The CREATE TABLE SQL in this example is formatted using PostgreSQL syntax, but it is worth noting that Django generates the corresponding SQL statement based on the database backend type specified in the configuration file.
  • Django supports MySQL 5.5 and higher.

3 ORM in Django

3.1 Django project uses MySQL database

  • In the Django project file, configure the database connection information:
DATABASES = {
    "default": {
        "ENGINE": "",
        "NAME": "Your database name",  # You need to create a database manually        "USER": "Database username",
        "PASSWORD": "Database Password",
        "HOST": "databaseIP",
        "POST": 3306
    }
}

Write the following code in the __init__.py file of the Django project to tell Django to use the pymysql module to connect to the MySQL database:

import pymysql
pymysql.install_as_MySQLdb()

3.2 Models custom fields (understand it as the main one)

class UnsignedIntegerField():
    def db_type(self, connection):
        return 'integer UNSIGNED'
class FixedCharField():
    """
     Custom char type field class
     """
    def __init__(self, max_length, *args, **kwargs):
        super().__init__(max_length=max_length, *args, **kwargs)
         = max_length
    def db_type(self, connection):
        """
         The field type that qualifies the generated database table to be char and the length is the value specified by length
         """
        return 'char(%s)' % 
class Class():
    id = (primary_key=True)
    title = (max_length=25)
    # Use the fields of type char as customized above    cname = FixedCharField(max_length=25)

Common methods for ORM query

4.1 Commonly used query operations

# Get all book objects, the result is an object list()  
# Get the object that meets the criteria(**kwargs)  
# Filter all those that meet the criteria, the result is an object list(**kwargs)  
# Filter out all those that do not meet the criteria, and the result is an object list. There has always been a question in this place. It seems that if the foreign key is excluded, it will not work.(**kwargs)  
# Dictionary list [{id:1,name:20},{id:2,name:18} ], values('id') are not specified in brackets, and only the specified ones are displayed if specified, [{id:1},{id:2,}]().values("id","name")  
# Tuple list, [ (1,20), (2,18)] is the same as above, displays the specified content when specified().values_list("id","name")  
# Arrange in ascending order by id().order_by("id")  
# Arrange in descending order of id().order_by("-id")  
# First, arrange the same age by id in descending order.().order_by("age", "-id") 
# Invert the result; Note that the reverse must be sorted before, otherwise the reverse will be invalid; or specify ordering=("id", ) in the meta in the Book class in the file. Note that the comma must have().order_by("id").reverse()  
# Deduplication, when the obtained result appears multiple times when the same object in the Queryset list is deduplication, only one().values("id","name").distinct():  
# Count, you can count the number of results, such as counting the number of elements in Queryset.().count() 
# Get the first item in the result, even if the previous result list is empty, there will be no error().first()  
# Get the last one in the result().last()  
# Determine whether there is something in the Queryset list, and the result is True or False;().exists() 

4.2 Return value

The method to return the object list (Queryset) is

  • all()
  • filter()
  • ordey_by()
  • exclude()
  • values()
  • values_list()
  • reverse()
  • distinct()

The method to return a single object is

  • first()
  • last()
  • get()
  • create()

Return to determine the Boolean value

  • exists()

Returns the number returned

  • count()

4.3 Query API (QuerySet API)

4.3.1 ------ filter -----

filter(**kwargs)

Returns a new QuerySet that contains objects that match the given filter criteria.

These filters (**kwargs) are described in detail in the field filter (Field looksups) below. Multiple conditions are AND relationships in SQL statements.

# Conditional query.  (You can connect multiple conditions through commas) Return the QuerySet query set (can be traversed)# __exact equals.  __exact can be omitted.  (__iexact is case-insensitive)(title__exact='The Eight Tribes of the Heavenly Dragon')
# Equivalent (title__exact='Tianlong Bashi')(title='The Eight Tribes of the Heavenly Dragon')
# __contains Contains.  Fuzzy query.  (__icontains is case-insensitive)(title__contains='sky')
# __endswith ends with...  __startswith starts with...  (__iendswith is case-insensitive)(title__endswith='department')
# __isnull Whether it is empty.  True: Expressed as null.  False means not null.(title__isnull=False)
# __in Range query.(id__in=[1, 3, 5])
# __range range query, query ids from 1 to 5(id__range=[1, 5])
# greater than less than(id__gt=3)  # Greater than(id__lt=3)  # Small(id__gte=3)  # greater than or equal to(id__lte=3)  # Less than or equal to# Date query, where __gt, __lt, __gte, and __lte all use dates(pub_date__gt=date(1980, 1, 1))
# Date query(pub_date__year=1980)  # Year(pub_date__month=1980)  # moon(pub_date__day=1980)  # day(pub_date__week_day=1980)  # Weekly(pub_date__hour=1980)  # hour(pub_date__minute=1980)  # point(pub_date__second=1980)  # Second

This is the end of this article about the detailed explanation of Django ORM. For more related Django ORM content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!