Django 项目就是基于 Django 框架开发的 Web 应用,它包含了一组配置和多个应用,我们把应用称之为 App,在前文中对它也做了相应的介绍,比如 auth、admin,它们都属于 APP。
一个 App 就是一个 Python 包,通常一个 App 可以包含模型、视图、模板和 URL 配置文件,可以被应用到多个 Django 项目中,因为它们的本质就是可被重用的 Python 软件包。
Django 的设计目标是让开发者关注应用的功能逻辑的实现。
所以,创建应用的过程是非常简单的,利用 manage.py 提供的 startapp 命令就可以创建一个APP。
具体命令如下所示:
# 语法
# python manage.py startapp 应用名
python manage.py startapp index
startapp 同样也属于 manage.py 的子命令,用来创建 Django 的应用。
执行这个命令不会在命令行看到任何输出,但是可以在 manage.py 的同级目录下看到多出了一个 index 目录:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oKUUkQJy-1681381102308)(imgs\企业微信截图_20230408154840.png)]
我们对这些文件做逐一的解释:
__init__.py
文件标识 index 应用是一个 Python 包__init__.py
文件标识 migrations 是一个 Python 包这就是 index 应用涉及到的所有文件,当然在实际的开发工作中,该应用目录下的文件也不是一成不变的,开发者根据自己的需要会相应的增加文件或者子目录,比如 urls.py 文件或者存储静态文件的 static 目录等。所以大家千万不要认为 Django 框架自动生成的目录,无需我们做其他操作或者更改,这是使用 Django 的一个误区。
应用创建完成后,我们还需要在 settings.py 配置文件中对其进行添加。
我们已经对 INSTALLED_APPS 做了介绍,把我们创建的应用添加到这个列表,如下所示:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]
用如上方式添加完成后,就可以让 index 应用的和整个项目融为一体了。
接下来,就可以正式进入开发应用阶段了,通过实现一些小的功能点,让我们更加全面的了解 Django 框架。
ORM (Object Realtional Mapping)即对象关系映射,它是一种基于关系型数据库的程序技术。ORM 允许你使用类和对象对数据库进行操作,这大大提高了对数据库的控制,避免了直接使用 SQL 语句对数据库进行操作。这种程序技术的底层主要是通过映射机制实现的,有兴趣的可以自己研究一下!
Web 开发中对数据库的操作是必不可少的,然而每种数据库的操作方式以及用法不尽相同。由于 Django 中 ORM 的存在,为我们操作不同种类的数据库提供了统一的方法,ORM 适配了多种常用的关系型数据库,例如 PostgreSQL、MySQL、Oracle、Sqlite3 等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6X4kOAug-1681381102310)(imgs\企业微信截图_20230408161112.png)]
那么在 Django 中如何使用 ORM 模块来定义一张数据表呢?
在定义数据表之前,我们应该首先理解什么是模型类。
模型类
其实模型类本质上属于一个 Python 类,只不过在 Django 中称之为做模型类 ,它是由 django.db.models.Model 派生出的子类
通过上述介绍,我们可以这样理解:Django 中模型类就相当于 ORM 模块。
定义数据表
现在有一张用户信息表 UserInfo,它有两个字段 name 和 password,可以定义如下:
class UserInfo(models.Model):
name = models.CharFiled(max_length=100)
password = models.CharFiled(max_length=100)
通过以上代码,UserInfo 数据表就已经创建完成,我们对代码进行逐行解析:
下面我们用 ORM 定义 index 应用所需的数据表,首选找到 index 应用下的 models.py 文件。
在文件里添加如下代码:
from django.db import models
# Create your models here.
# 创建book表
class Book(models.Model):
title = models.CharField(max_length=30, unique=True, verbose_name='书名')
public = models.CharField(max_length=50, verbose_name='出版社')
price = models.DecimalField(max_digits=7, decimal_places=2, verbose_name='定价')
retail_price = models.DecimalField(max_digits=7, decimal_places=2, verbose_name='零售价', default="30")
def __str__(self):
return "title:%s pub:%s price:%s" % (self.title, self.public, self.price)
# 创建作者表
class Author(models.Model):
name = models.CharField(max_length=30, verbose_name='姓名')
email = models.EmailField(verbose_name='邮箱')
def __str__(self):
return '作者:%s' % self.name
# 创建用户信息表
class UserInfo(models.Model):
username = models.CharField(max_length=24, verbose_name='用户注册')
password = models.CharField(max_length=24, verbose_name='密码')
通过上述代码,我们定义了一个名叫 Book 的数据表。
数据表由以下字段构成书名(title)、出版社(public)、价格(price)、零售价(retail_price),而且对每个字段都做添加了相应的字段属性以及字段选项。
Model 中添加的字段都是 Field 类型的实例,不同的 Field 类型可能会支持不同的字段选项,但是也有很多字段选项是通用的,即可以用在任何一种 Field 类型中。这里介绍一些常用且重要的通用字段选项,它们都有对应的默认值,这些字段选项都是可选的,理解这些有助于更好地使用它们。
blank
默认值是 False,设置为 True 时,字段可以为空。设置为 False 时,字段是必须填写的。如果是字符型字段 CharField 和 TextField,它们是用空字符串来存储空值的。
unique
默认值是 False,它是一个数据库级别的选项,规定该字段在表中必须是唯一的。
null
默认为 False,如果此选项为 False 建议加入 default 选项来设置默认值。如果设置为 True,表示该列值允许为空。日期型、时间型以及数字型字段不接受空字符串。所以当设置 IntegerField,DateTimeField 型字段可以为空时,需要将 blank 与 null 均设为 True 才可以。
db_index
默认值是 False,如果设置为 True,Django 则会为该字段创建数据库索引,如果该字段经常作为查询的条件,那么就需要设置 db_index 选项,从而加快数据的检索速度。
db_column
这个选项用于设置数据库表字段的名称。如果没有指定,Django 默认使用 Model 中字段的名字。
default
用于给字段设置默认值,该选项可以设置为一个值或者是可以调用对象,但不能是可变对象,不同字段类型默认值也不同,比如 BooleanFiled 布尔类型 default 值为Ture 或者 False。主要的使用场景是当一个字段的值被用户省略时,后台服务器自动为该字段的设置默认值。
primary_key
默认值是 False,如果设置为 True,表示该字段为主键,在 Django 中 默认 id 为主键,也就是说即使你的数据表中没有创建 id 字段,Django 也会自动为你创建 id 字段并将其设置为主键。如果你在表中设置了其他字段为主键的时,那么 Django 将取消为 id 字段设置主键。
choices
这个选项用于给字段设置可以选择的值。它是一个可迭代对象,即列表或者元组,其中每一个元素都是一个二元组(a,b)的形式,a 是用来选择的对象,b 是对 a 的描述信息。比如我们对某个人性别定义数据表如下所示:
# 创建表
class UserInfo(models.Model):
# 定义chocies参数的对应关系,以元组(或者列表)的形式进行表述:
choices = (
(male, '男性'),
(female, '女性'),
)
gender = models.CharField(max_length=2,choices = choices,default='male')
verbose_name
设置此字段在 admin 后台管理系统界面上的显示名称,如果没有设置这个字段,Django 将会直接展示字段名并且将字段中的下划线转变为空格。
上面我们创建好了 index 应用所需的数据表,下一步就是执行数据库的迁移,之后让我们再来看一下又有什么新的变化发生呢?数据库迁移的两个命令分步骤执行,如下所示:
python manage.py makemigrations
python manage.py migrate
执行完毕后会在命令行得到如下输出:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rGSRpXFI-1681381102310)(imgs\企业微信截图_20230408165919.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPM3pShC-1681381102311)(imgs\企业微信截图_20230408165958.png)]
若迁移过程中出现报错提示,首先检查您的 models.py 文件是否正确书写,除此之外,也可能由于 Django 与 MySQL 版本问题导致报错。
从上述输出结果可以看出,我们对 index 应用进行了数据库迁移工作。
并且在数据库中创建了三张表,分别是 Author、Book、UserInfo。
而且在 index 应用下的 migrations 目录下生还成了一个 0001_initial.py 的文件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Tj9e1aM-1681381102312)(imgs\企业微信截图_20230408170141.png)]
这个迁移文件包含了创建数据表时用到的所有信息,这是一个临时的过度文件。
__str__
__str__
方法是 Python 中的 "魔术” 方法,它是为 print 这样的打印函数设计的,它属于 python 的 object 基类的一个方法,也就是说 python 所有的类都有该方法,当然 Django 的 modle 类也有。如果没有这个方法定义,打印对象会显示对象的内存地址,但是这样的显示方式不够友好,且不利于调试,而用 __str__
方法后,可以在 print 时得到易于人阅读的信息,在如下所示:
# 直接print打印
class TestClass:
def __init__(self):
self.name = 'testcase'
t = TestClass() #实例化对象
print(t) # 结果显示:<__main__.TestClass object at 0x8f5c27b42367>
# __str__方法
class TestClass:
def __init__(self):
self.name = '小明'
def __str__(self):
return self.name
t = TestClass() #实例化对象
print(t) # 结果显示:小明
本节内容为 index 应用创建了数据表,并且一步步带领大家实现了如何自定义模型类以及完成了数据表的迁移的,而且对产生的迁移文件也做了介绍,接下来我们将学习 Django 的后台管理系统,看看它是如何配合 ORM 使用的。
Django 的后台管理系统是非常出色的,新建项目以后,Django 就为我们设置好了后台管理系统的各种功能。
我们知道,Web 站点上某些内容的改动是后台管理员来完成的,如果管理员直接用 Shell 或者 SQL 语句来修改,不仅麻烦,而且容易操作失误,从而导致数据不一致的结果。假如是一个不懂编程的人呢?应该怎么去操作呢?上述问题,说明了构建一个后台管理系统的重要性,通过后台管理系统为管理员提供一种便捷有效的操作方式。
后台管理系统主要是对数据表的存储做专门的管理,例如针对微博或者论坛类的站点,管理员需要删除不合规的文章,或者公司内部需要发布新的话题等,这些都是通过数据表的管理实现的。单一功能的后台系统比较容易构建,但是如果功能增多情况下,就需要对多个数据表做管理,这就增加了开发人员的重复性工作。Django 提供的后台管理系统很好的解决了这个问题。
通过命令创建超级管理员账户,命令如下所示:
python manage.py createsuperuser --username=admin [email protected]
这里将用户名设置为 admin,邮箱设置为 [email protected],也可以根据自己的需要去修改。如果在 createsuperuser 后面不加任何内容,Django 会提示用户输入用户名和邮箱。当前命令执行后,需要重复输入两次密码,密码可以根据自己的需要设置,但是密码不能过于简单。
老师的密码:admin
如下图所示,表示创建成功:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-avqBrpJZ-1681381102312)(imgs\企业微信截图_20230408195344.png)]
注意:输入密码的时候,不会显示。
注意:超级用户拥有所有权限,方便技术人员或非技术人员以可视化的形式对应用数据记录实现增删改查的操作。
启动 BookStore 项目,然后在浏览器地址栏输入 127.0.0.1:8000/admin 访问,输入刚刚创建的超级用户名以及密码进行登录。如下所示登录成功:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Le16t3h-1681381102313)(imgs\企业微信截图_20230408200117.png)]
在admin.py文件中声明
那么如何把自定义的数据表 Model 注册到管理后台呢?
也就是说要把 Model 显示在 Admin 后台管理系统界面,需要做哪些操作呢?
当我们使用 startapp 命令创建 index 应用的时候会自动创建 admin.py 文件,想要把自定义的 Model 注册到管理后台,就需要在 admin.py 文件中进行声明,添加如下代码:
from django.contrib import admin #Django自动在admin.py文件中导入
from index.models import Book, Author,UserInfo #这个需要我们自己导入相应的模型类(数据表)
admin.site.register([Book,Author,UserInfo])
通过上述代码,我们就完成了将 Model 注册到后台管理系统的操作,其实实现的过程也非常的简单,首先通过 django.contrib 的标准库引入 admin 应用,然后把 index 应用下我们自定义的三张数据表引入,最后我们调用 admin.site.register() 方法实现模型类的注册。多个模型类一起注册我们使用列表的形式来统一注册,如果是单一的模型类注册,我们可以使用以下方式即可:
admin.site.register(Book)
至此我们就完成了数据表在 Admin后台管理系统的可视化操作,我们再次使用ctrl+F5
刷新后台管理系统的显示页面,可以得到如下结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMj8B5sf-1681381102314)(imgs\企业微信截图_20230408201640.png)]提示:图中每张数据表的名字都加上了s,这是Django自动设定的,我们可以通过相应的修改将其去掉,在后续章节我们将介绍。
虽然看似页面简单并且没有太多的附加功能,但是对于简单的增删改操作而言已经足够使用了。我们打开其中的 UserInfos 数据表来查看,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-04jeQn1L-1681381102315)(imgs\企业微信截图_20230408202253.png)]
点击增加 USERI INFO 按钮会得到如下页面,在此页面我们可以进行数据的添加、编辑、保存操作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0kiKCA02-1681381102316)(imgs\企业微信截图_20230408203359.png)]
Admin 应用在数据库迁移的过程中只创建了 django_admin_log 一张表 ,用于记录通过管理后台完成的对 Model 的增删改操作。
如下所示,是数据库迁移过程中生成的所有数据表:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ih1e8vKp-1681381102317)(imgs\企业微信截图_20230408204534.png)]
查看 django_admin_log 表结构, 如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAtzGdoo-1681381102319)(imgs\企业微信截图_20230408204632.png)]
这些字段含义只做简单了解即可,如下所示:
id 是自增的主键
action_time:datetime 类型,保存操作发生的日期和时间
object_id:longtext 类型,保存修改对象的主键
object_repr:varchar 类型,保存修改后的对象执行 repr 函数的值,repr 是 Python 的内置函数,用于将对象转换为字符串;
action_flag:无符号 smallint 类型,用于记录操作类型 ADDITION(值为1,表示添加)、CHANGE(值为 2,表示更新)、DELETION(值为 3,表示删除);
change_message:longtext 类型,用于保存修改对象的详细描述;
content_type_id:int 类型,外键关联 ContentType 对象;
user_id:int类型,外键关键User对象(默认值),记录执行操作的用户。
本节我们在 Admin 后台管理系统实现了数据表的可视化。
通过这个功能我们就可以对数据表进行管理,极大的方便了 Web 站点的管理人员。
on 的内置函数,用于将对象转换为字符串;
action_flag:无符号 smallint 类型,用于记录操作类型 ADDITION(值为1,表示添加)、CHANGE(值为 2,表示更新)、DELETION(值为 3,表示删除);
change_message:longtext 类型,用于保存修改对象的详细描述;
content_type_id:int 类型,外键关联 ContentType 对象;
user_id:int类型,外键关键User对象(默认值),记录执行操作的用户。
本节我们在 Admin 后台管理系统实现了数据表的可视化。
通过这个功能我们就可以对数据表进行管理,极大的方便了 Web 站点的管理人员。