一个后台如果没有数据库可以说废了一半。日常开发中大多数时候都在与数据库打交道。Django
为我们提供了一种更简单的操作数据库的方式。
在 Django
中,模型(Model
)是用来定义数据库结构的类。每个模型类通常对应数据库中的一个表,类的属性对应表中的列。通过定义模型,Django
的 ORM
(Object-Relational Mapping)可以将 Python
对象映射到数据库表,并提供一套 API
来进行数据库操作。
本文介绍模型的用法。
ORM
在了解模型之前先了解一下什么是 ORM
。
ORM
(Object-Relational Mapping,对象关系映射)是 Django
框架中用于与数据库进行交互的一种工具。ORM
允许开发者使用 Python
对象和类来操作数据库表,而无需直接编写 SQL
查询。这样,开发者可以以更加直观和面向对象的方式处理数据库操作。
简单来说,ORM
就是让我们使用编程语言而不是 SQL
语句去与数据库进行交互。
数据库和面向对象的对应关系:
- 数据表 - 类
- 数据行 - 对象
- 字段 - 属性
配置MySQL数据库
在 Django
中默认使用的数据库是 SQLite
,而在我们这边很多中小企业喜欢用 MySQL
,所以使用 Django
操作 MySQL
前需要先配置一下。
在配置之前,需要先安装好 MySQL
,下载地址:dev.mysql.com/downloads/m…
安装好 MySQL
后,在 Django
项目中打开 settings.py
文件,DATABASES
这段默认的配置是这样的:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3') } }
我们要用 MySQL
,就要改成这样:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_demo' } }
这里的 NAME
指的是数据库的名称,需要在 MySQL
里创建一个 django_demo
的数据库。
打开终端,连接 MySQL
,然后创建 django_demo
数据库。
# 连接 MySQL 数据库 mysql -u root -p # 然后输入密码 # 创建数据库 create database django_demo;
然后继续设置 settings.py
文件的 DATABASES
这段配置。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_demo', 'HOST': '127.0.0.1', 'USER': 'root', 'PASSWORD': '12345678' } }
逐个字段解释一下:
ENGINE
:这个字段指定Django要使用的数据库引擎常用的引擎包括:
'django.db.backends.postgresql'
(PostgreSQL)'django.db.backends.mysql'
(MySQL)'django.db.backends.sqlite3'
(SQLite)'django.db.backends.oracle'
(Oracle)
NAME
:指定要连接的数据库的名称。HOST
:数据库服务器的地址。127.0.0.1
表示本地服务器,如果数据库在远程服务器上运行,则需要指定远程服务器的IP地址或域名。USER
:连接到数据库的用户名。PASSWORD
:用户名对应的密码。
我在自己电脑的用户名和密码都设置得比较简单,在生产环境千万别设置这么简单的账号密码。
安装 PyMySQL
在 Django
中,默认使用的 MySQL
数据库连接库是 MySQLdb
。不过,由于MySQLdb
在某些情况下的兼容性问题和安装难度,有时会选择使用 PyMySQL
作为替代。
但使用 PyMySQL
,需要做一些额外的配置。
首先,安装PyMySQL
。
pip install pymysql
然后在 Django
项目的 __init__.py
文件(通常在与settings.py
文件同级的目录下)中添加以下代码,以确保 Django
使用 PyMySQL
来代替 MySQLdb
。
import pymysql pymysql.install_as_MySQLdb()
数据迁移
执行数据库迁移是 Django
开发流程中的一个重要步骤。迁移用于同步数据库模式和 Django
模型的定义。之后对数据库做完的所有操作,最后都要执行“生成迁移文件”和“迁移数据库”这两项操作。
执行数据库迁移的步骤
1. 生成迁移文件
生成迁移文件是将模型的更改(创建、修改、删除模型和字段)记录下来,生成迁移文件的命令是:
python manage.py makemigrations
这个命令会扫描你定义的模型(位于 Django
应用的 models.py
文件中),并生成描述这些更改的迁移文件。这些迁移文件通常存储在每个应用的 migrations
目录下。
2. 迁移数据库
将迁移文件应用到数据库中,使数据库的结构与模型定义一致,命令是:
python manage.py migrate
这个命令会执行所有未应用的迁移文件,更新数据库模式。
在没有定义自己的模型之前,也能执行数据库迁移,这是因为 Django
自带了一些默认的应用程序(如认证系统、会话管理、站点管理等),这些应用程序依赖于一些数据库表。这些表的迁移文件已经包含在 Django
框架中,当执行迁移时,Django
会为这些默认应用程序创建必要的数据库表。
创建模型
在创建模型之前我们需要知道这个模型属于哪一个应用下的。
我们前面已经创建了一个 blog
应用了,这个应用的作用是对博客进行操作。
而每一篇博客应该都有一个作者,所以我们再创建多一个用户相关的应用,叫 account
。
python manage.py startapp account
创建完这个应用记得在项目的 settings.py
里注册这个应用。
此时我们就有2个应用了。
在这两个应用中都各自有 models.py
文件,这是我们要操作的目标文件。
创建用户相关的模型
先打开 account/models.py
这个文件,创建用户相关的数据表。
# blog/models.py from django.db import models # 创建一个用户表 class User(models.Model): id = models.AutoField(primary_key=True) # 用户名 username = models.CharField('用户名', max_length=30, null=True, blank=True, unique=True) # 密码 password = models.CharField('密码', max_length=30) # 邮箱 email = models.EmailField('邮箱', unique=True, null=True, blank=True)
这里的代码很简单,简单来说就是通过 class
创建一个 User
类,这个类的参数是 models.Model
,这个是固定写法。
然后分别创建4个字段,逐一介绍一下:
id
:
models.AutoField
:自增字段primary_key=True
:主键
username
:用户名
models.CharField
:字符字段max_length=30
:最大长度30null=True
:允许为null
。null
的值默认是False
。这里主要影响MySQL
入库时的值。blank=True
: 允许为null
。默认False
。决定这个字段是否为空,比如登录时这里用户名是否为空。如果True
的话可以设置为空。这里主要影响程序逻辑。unique=True
: 该字段在整个表中必须是唯一的。,默认False。
password
:密码email
:邮箱
密码和邮箱的配置在前面的字段中解释过了,这里不再啰嗦。
创建博客模型
接下来就要配置 blog
的 models.py
了。
# blog/models.py from django.db import models from account.models import User class Article(models.Model): id = models.IntegerField(primary_key=True) # 标题 title = models.CharField(max_length=120) # 内容 content = models.TextField() # 发布时间 publish_date = models.DateTimeField() # 关联用户 user = models.ForeignKey(User, on_delete=models.CASCADE)
这里引入了 account.models
用户应用的 models
。
在 blog/models.py
中部分字段的配置和 account/models.py
是差不多的,其中有区别的是:
id
:
models.IntegerField
:用于存储整数。
content
:内容
models.TextField
:用于存储长文本,不需要指定max_length
。
publish_date
:发布时间
models.DateTimeField
:用于存储日期和时间。
user
:关联用户
models.ForeignKey
:要关联的外键,用于定义多对一关系。这里传入的第一个参数是要关联的外键的模型;第二个on_delete=models.CASCADE
表示关联删除,当用户被删除时,对应的文章也会一起被删除。
执行迁移
在 models.py
里创建好数据表的代码后,生成迁移文件,执行迁移操作。就能在 MySQL
中看到这些表了。
创建迁移文件,再执行迁移命令:
python manage.py makemigrations python manage.py migrate
看到以上信息证明操作执行成功。因为我是在Mac上操作,我电脑有python2和python3两个环境,所以我需要使用 python3 xxxx
这种方式去执行。
接下来在数据库中看看这两个表。
设置 meta 元数据
有没有发现,前面创建的 user
和 article
两个表都有一个应用名的前缀和下划线。
这是 Django
默认的行为,如果你不想要这个应用名,可以在建表的时候设置 meta
。
在 account/models.py
中的代码就变成这样写:
# account/models.py from django.db import models # 创建一个用户表 class User(models.Model): id = models.AutoField(primary_key=True) # 用户名 username = models.CharField('用户名', max_length=30, null=True, blank=True, unique=True) # 密码 password = models.CharField('密码', max_length=30) # 邮箱 email = models.EmailField('邮箱', unique=True, null=True, blank=True) class Meta: # 自定义表名 db_table = 'user' # 表别名 verbose_name = '用户表'
在 blog/models.py
中的代码就变成这样写:
# blog/models.py from django.db import models from account.models import User class Article(models.Model): id = models.IntegerField(primary_key=True) title = models.CharField(max_length=120) content = models.TextField() # 发布时间 publish_date = models.DateTimeField() # 关联用户 # on_delete=models.CASCADE: 表示关联删除,当用户被删除时,对应的文章也会一起被删除。 user = models.ForeignKey(User, on_delete=models.CASCADE) class Meta: # 自定义表名 db_table = 'article' # 表别名 verbose_name = '文章信息表'
在创建表的类里面再添加一个 Meta类,设置完元信息后再执行生成迁移文件和执行迁移的命令即可。
python manage.py makemigrations python manage.py migrate
此时再查看 django_demo
这个库就能看到 article
和 user
两个表了。
ORM 增删改查(CRUD)
终于到了本文最后一部分内容了。
在创建完表后,接下来就要对数据进行“增删改查”操作了。也就是大家常说的“CRUD”。
- C(create):增加、插入数据
- R(read):读取数据
- U(update):更新、修改数据
- D(delete):删除数据
因为现在还没有具体的界面,所以我先使用 shell 操作。
打开终端,进入项目目录,然后输入下面这条命令就可以使用 shell 操作。
python manage.py shell
新增数据
首先要有数据。新增数据的方法有几个:
save()
:保存create()
:新增数据bulk_create()
:批量新增数据
save()
先试试 save()
方法。
from account.models import User user_obj_zhangsan = User(username='zhangsan', password='123456', email='zhangsan@qq.com') user_obj_zhangsan.save()
上面这段代码的意思是在 User
这个表里插入一条数据。
要操作 User
表,首先要导入 User
模型,就是用到 from account.models import User
这句代码。
然后创建一个 user_obj_zhangsan
对象,调用 User
模型,分别传入用户名 username
、密码 password
和 邮箱 email
。
最后调用 save()
方法。
此时打开数据库的 User
表查就能查到刚刚保存的这条数据。
用到的查询命令是 select * from user;
create()
接下来试试 create()
方法。
前面用 save()
方法首先创建一个对象,然后再调用 save()
保存紧数据库。而 create()
方法可以简单理解成将 save()
所需要的两步操作合成一步。
from account.models import User user_obj_lisi = User.objects.create(username='lisi', password='12345666666', email='lisi@qq.com')
需要注意,这里用到的是 User.objects.create(xxx)
。
在查查数据库,可以看到 lisi
这条数据了。
bulk_create()
save()
和 create()
都是逐条数据插入的,如果需要批量插入数据的话可以使用 bulk_create()
。
from account.models import User user_obj_wangwu = User(username='wangwu', password='22222', email='wangwu@qq.com') user_obj_zhaoliu = User(username='zhaoliu', password='33333', email='zhaoliu@qq.com') user_list = [user_obj_wangwu, user_obj_zhaoliu] User.objects.bulk_create(user_list)
在这段代码中,创建了 wangwu
和 zhaoliu
两个用户对象,然后把这两项放进 user_list
列表里。最后调用 User.objects.bulk_create()
方法插入数据。
查询数据
查询数据的常用方法有3种:
all()
:返回所有数据get()
:按照查询条件返回单条数据filter()
:按照查询条件返回多条数据
当然啦,查询数据的方法是不止这三种的,入门阶段先介绍这两种比较常用的方法。
all()
all()
方法可以查询所有数据,比如查询我们刚刚创建的4个用户。
from account.models import User users = User.objects.all() print(users)
可以清楚的看到,打印输出了4条数据。
在上一段代码的基础上,我们可以循环输出看看这4条数据的 username
分别是什么。
for user in users: print(user.username)
这就是 all()
的使用方法。
get()
有时候我们不需要把所有数据都查出来,而是需要按条件进行查询。
此时可以使用 get()
和 filter()
,先介绍 get()
。
get()
方法会按照指定的条件去查询,并返回一条数据。在需要登录的场景,可以通过 get()
的方式去查询相关的用户名和密码。
如果查询的数据不存在会报错,建议使用try包着。
如果查询的记录多与1条也会报错!
比如我们要查询 id
为2的用户,并打印它的 username
,可以这么写。
from account.models import User user = User.objects.get(id=2) print(user.username)
因为在 user
表里,id
就是主键,我们同样可以通过主键去查询。
user = User.objects.get(pk=2) print(user.username)
除此之外你还可以通过 username
或者其他字段去查询。
user = User.objects.get(username='zhangsan')
filter()
如果你需要按条件范围去查询,可以使用 filter()
方法。
比如查询 id
大于2的用户。
from account.models import User users = User.objects.filter(id__gt=2) for user in users: print(user.username)
这里可能你会疑惑,为什么不是 id>2
,而是 id__gt=2
?
这是 Django
的语法。
比较时常用的关键字:
- gt:大于某个值
- gte:大于或等于某个值
- lt:小于某个值
- lte:小于或等于
- isnull:是否为空
是否包含**字符串:
- icontains:不区分大小写
- contains:包含**值
- in:在**选项(列表)之内
以**开始/结束
- startswith, istartwith:以**开头
- endswith, iendswith:以**结束
其他查询方法之后用到再讲解,现在只需大概知道可以用上面的方法去查即可。
更新/修改数据
修改数据的方法同样有3种:
save()
:修改单条update()
:修改单条数据的多个字段
在修改数据之前,首先我们要明确修改哪条数据。所以会用到 get()
和 filter()
方法。
save()
save()
和前面讲新增数据时用到的 save()
是一样的,有点覆盖的意思。
举个例子,将 username
为 zhangsan
的 email
从 @qq
修改成 @163
。
from account.models import User user = User.objects.get(username='zhangsan') user.email = 'zhangsan@163.com' user.save()
此时我们在数据库查一下 zhangsan
这条数据的所有信息,可以看到邮箱已经改过来了。
update()
update()
方法可以将上面使用 save()
的代码简化到一行。
比如,此时我要将 lisi
的 password
改成 666
。
from account.models import User User.objects.filter(username='lisi').update(password='666')
再查看一下数据库。
需要注意!用 update()
方法前,要用 filter()
找到要修改的那些数据,不能使用 get()
删除数据
最后要介绍的是删除数据。在 Django
里使用 delete()
方法可以删除数据。但真实项目中很少用到这个方法,因为这个方法会真实删除数据库里的数据,删掉后要恢复就比较麻烦了。所以通常会给数据增加一个字段来判断这条数据是否被删除,也就是逻辑删除,是一种假删除的方法,用到的是前面介绍的 update()
方法来操作。
但学技能要学全,我们还是要了解一下 delete()
怎么使用。
delete()
delete()
的用法和前面 save()
、update()
都差不多。
首先还是要找到要删除的那条数据,用的还是 filter()
方法去查找。
找到后再调用 delete()
方法直接删除即可。
比如,我要删除 username
是 zhaoliu
这条数据。
from account.models import User user = User.objects.filter(username='zhaoliu') user.delete()
执行完上面的代码后,再查一下数据库,zhaoliu
这条数据已经消失了。
在日常开发中,“查数据”的工作是最大的。本文只是简单的介绍了 get()
和 filter()
方法。真正查数据的话其实还有很多方法去协助我们的,而且还有很多“且”和“或”的条件判断。
在入门阶段可以先浅浅的学一下,毕竟学太多也记不住。更重要的还是要在项目中实战。实战时遇到不懂的地方再查,记忆就深刻很多了。