Django Models
Django provides excellent support for various databases, including PostgreSQL, MySQL, SQLite, and Oracle.
Django offers a unified API for these databases. We can choose different databases based on our business requirements.
MySQL is the most commonly used database for web applications. In this section, we will use MySQL as an example. You can learn more about MySQL basics through our MySQL Tutorial.
If you haven't installed the MySQL driver, you can install it with the following command:
sudo pip3 install pymysql
Django ORM
Django models use its built-in ORM.
Object Relational Mapping (ORM) is used to convert data between incompatible type systems in object-oriented programming languages.
ORM acts as a bridge between the business logic layer and the database layer.
ORM automatically persists objects in the database using metadata that describes the mapping between objects and the database.
Benefits of using ORM:
- Increases development efficiency.
- Smoothly switches between different databases.
Drawbacks of using ORM:
- Conversion of ORM code to SQL statements takes time, reducing execution efficiency.
- Long-term use of ORM can decrease SQL writing skills.
ORM parsing process:
- ORM converts Python code into SQL statements.
- SQL statements are sent to the database server via pymysql.
- The database executes the SQL statements and returns the results.
ORM mapping table:
Database Configuration
How Django Uses MySQL Database
Create a MySQL database (ORM cannot operate at the database level, only at the table level) with the following syntax:
create database database_name default charset=utf8; # To prevent encoding issues, specify utf8
For example, we create a database named tutorialpro with utf8 encoding:
create database tutorialpro default charset=utf8;
In the settings.py file of our project, find the DATABASES configuration item and modify it as follows:
HelloWorld/HelloWorld/settings.py: File Code:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # Database engine
'NAME': 'tutorialpro', # Database name
'HOST': '127.0.0.1', # Database address, local IP 127.0.0.1
'PORT': 3306, # Port
'USER': 'root', # Database username
'PASSWORD': '123456', # Database password
}
}
If you are using Python 2.x and have added Chinese comments, you need to add # -*- coding: UTF-8 -*-
at the top of the HelloWorld/settings.py file.
The above settings include the database name and user information, which should match the corresponding settings in MySQL. Django connects to the appropriate database and user based on these settings.
Next, inform Django to use the pymysql module to connect to the MySQL database:
Example
# Import modules and configure in the __init__.py file at the same level as settings.py
import pymysql
pymysql.install_as_MySQLdb()
Defining Models
Creating an APP
Django requires the creation of an app to use models. We create an app named TestModel with the following command:
django-admin startapp TestModel
The directory structure is as follows:
HelloWorld
|-- HelloWorld
|-- manage.py
...
|-- TestModel
| |-- __init__.py
| |-- admin.py
| |-- models.py
| |-- tests.py
| `-- views.py
We modify the TestModel/models.py file as follows:
HelloWorld/TestModel/models.py: File Code:
# models.py
from django.db import models
class Test(models.Model):
name = models.CharField(max_length=20)
The class name represents the database table name and inherits from models.Model
. The fields within the class represent the fields in the database table (e.g., name
), and their data types are specified by CharField
(equivalent to varchar
), DateField
(equivalent to datetime
), and the max_length
parameter restricts the length.
Next, locate the INSTALLED_APPS
setting in settings.py
as follows:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'TestModel', # Add this line
)
Run the following commands in the command line:
$ python3 manage.py migrate # Create table structures
$ python3 manage.py makemigrations TestModel # Inform Django that there are changes in our models
$ python3 manage.py migrate TestModel # Create table structures
Upon seeing lines like "Creating table…", your database table is created.
Creating tables ...
……
Creating table TestModel_test # Our custom table
……
The table name structure is: app_name_class_name (e.g., TestModel_test
).
Note: Even though we did not set a primary key in the models, Django will automatically add an id
as the primary key.
Common Error Messages
If you encounter the following error message when running the above commands:
The reason is that MySQLclient currently only supports up to Python 3.4. Therefore, if you are using a higher version of Python, you need to modify the following:
Find the base.py
file in the path ...site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql
from the error message and comment out these two lines of code (located at the beginning of the file):
if version < (1, 3, 13):
raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
Usually, clicking on the error code file path information will automatically jump to the line number in the error file, where we comment out the error line.
If you encounter the following error message:
Click on the error code file path, jump to the line number in the error file, and add the following line before the error line:
query = query.encode()
Database Operations
Next, add a testdb.py
file in the HelloWorld
directory (described below) and modify urls.py
:
HelloWorld/HelloWorld/urls.py: File Code:
from django.urls import path
from . import views, testdb
urlpatterns = [
path('tutorialpro/', views.tutorialpro),
path('testdb/', testdb.testdb),
]
Adding Data
To add data, you need to create an object first and then execute the save
function, similar to an SQL INSERT
:
HelloWorld/HelloWorld/testdb.py: File Code:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# Database operation
def testdb(request):
test1 = Test(name='tutorialpro')
test1.save()
return HttpResponse("<p>Data added successfully!</p>")
Visit http://127.0.0.1:8000/testdb to see the success message for data addition.
The output will be as follows:
Retrieving Data
Django provides various methods to retrieve data from the database, as shown in the following code:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# Database operations
def testdb(request):
# Initialization
response = ""
response1 = ""
# Retrieve all rows using the all() method of the model manager, similar to SQL's SELECT * FROM
list = Test.objects.all()
# filter is similar to SQL's WHERE, allowing conditional filtering
response2 = Test.objects.filter(id=1)
# Retrieve a single object
response3 = Test.objects.get(id=1)
# Limit the returned data, similar to SQL's OFFSET 0 LIMIT 2;
Test.objects.order_by('name')[0:2]
# Sort data
Test.objects.order_by("id")
# The above methods can be chained
Test.objects.filter(name="tutorialpro").order_by("id")
# Output all data
for var in list:
response1 += var.name + " "
response = response1
return HttpResponse("<p>" + response + "</p>")
Updating Data
Data can be modified using save() or update():
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# Database operations
def testdb(request):
# Update the name field of the entry with id=1 and save, similar to SQL's UPDATE
test1 = Test.objects.get(id=1)
test1.name = 'Google'
test1.save()
# Another method
# Test.objects.filter(id=1).update(name='Google')
# Update all entries
# Test.objects.all().update(name='Google')
return HttpResponse("<p>Update successful</p>")
Deleting Data
Deleting an object from the database can be done by calling the delete() method on that object:
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# Database operations
def testdb(request):
# Delete the data with id=1
test1 = Test.objects.get(id=1)
test1.delete()
# Another method
# Test.objects.filter(id=1).delete()
# Delete all data
# Test.objects.all().delete()
return HttpResponse("<p>Deletion successful</p>")