Django Web应用开发实战第七章
一、ORM框架
Django对各种数据库提供了很好的支持,包括PostgreSQL、MySQL、SQLite和Oracle,且为这些数据库提供了统一API方法,这些API统称为ORM框架。
通过Django内置的ORM框架可以实现数据库连接和读写操作。
二、模型定义与数据迁移
ORM框架是一种程序技术,用于实现 面向对象编程语言中不同类型系统的数据之间的转换,从效果上说,它创建了一个可在编程语言中使用的“虚拟对象数据库”,通过对虚拟对象数据库的操作,实现对目标数据库的操作,虚拟对象数据库与目标数据库是相互对应的。在Django中虚拟对象数据库也称为模型。模型字段如下:
- AutoField: 自增长类型,数据表的字段类型为整数,长度为11位
- BigAutoField: 自增长类型,数据表的字段类型为bigint,长度为20位
- CharField: 字符类型
- BooleanField: 布尔类型
- CommonSeparateIntegerField: 用逗号分割的整数类型
- DateField: 日期(Date)类型
- DatetimeField: 日期时间(Datetime)类型
- Decimal: 十进制小数类型
- EmailField: 字符类型,存储邮箱格式的字符串
- FloatField: 浮点数类型,数据表的字段类型变成Double类型
- IntegerField: 整数类型,数据表的字段类型为11位的整数
- BigIntegerField: 长整数类型
- IPAddressField: 字符类型,存储Ipv4地址的字符串
- GenericIPAddressField: 字符类型,存储Ipv4和Ipv6地址的字符串
- NullBooleanField: 允许为空的布尔类型
- PositiveIntegerField: 正整数的整数类型
- PositiveSmallIntegerField: 小正整数类型,取值范围0~32767
- SlugField: 字符类型,包含字母、数字、下划线和连字符的字符串
- TextField: 长文本类型
- TimeField: 时间类型,显示时分秒HH:MM[:ss[.uuuuuuu]]
- URLField: 字符类型,存储路由格式的字符串
- BinaryField: 二进制数据类型
- FileField: 字符类型,存储文件路径的字符串
- ImageField: 字符类型,存储图片路径的字符串
- FilePathField: 字符类型,从特定的文件目录选择某个文件
允许设置的参数
源码Field(django/db/models/fields/init.py)
- verbose_name: 默认None,在Admin站点管理设置字符的显示名称
- primary_key: 默认为False,若为True,则将字段设置成主键
- max_length: 默认为None,设置字段的最大长度
- unique: 默认为False,若为True,则设置字段的唯一属性
- blank: 默认为False, 若为True,则设置字段允许为空值,数据库将存储空字符串
- null: 默认为False,若为True,则字段允许为空值,数据库表现为NULL
- db_index: 默认为False,若为True,则以此字段来创建数据库索引
- default: 默认为NOT_PROVIDEDD对象,设置字段的默认值
- editable: 默认为True,允许字段可编辑,用于设置Admin的新增数据的字段
- serialize: 默认为True,允许字段序列化,可将数据转化为JSON格式
- unique_for_date: 默认为None,设置日期字段的唯一性
- unique_for_month: 默认为None,设置月份字段的唯一性
- unique_for_year: 默认为None,设置年份字段的唯一性
- choices: 默认空列表,设置字段的可选值
- help_text: 默认为空字符串,用于设置表单的提示信息
- db_column: 默认为None,设置数据表的列名称,若不设置,则字段名作为列名
- db_tablespace: 默认为None,如果字段已创建索引,那么数据库的表空间名称将作为该字段的索引名称。注意:部分数据库不支持表空间
- auto_created: 默认为False,若为True,则自动创建字段,用于一对一的关系模型
- validators: 默认为空列表,设置字段内容的验证函数
- error_message: 默认为None,设置错误提示
- 以上参数适用于所有字段
- 以下适用于Meta
- abstract: 若设置为True,则该模型为抽象模型,不会在数据库里创建数据表
- app_label:属性值为字符串,将模型设置为指定的项目应用,比如将index的models.py定义的模型A指定到其他的APP里
- db_table: 属性值为字符串,设置模型所使用的数据库的表名
- db_tablespace: 属性值为字符串,设置模型所使用的数据库的表名
- get_lastest_by: 属性值为字符串或列表,设置模型数据的排序方式
- managed: 默认为True,支持Django命令执行数据迁移;若为False,则不支持数据迁移功能
- order_with_respect_to: 属性值为字符串,用于多对多的模型关系,指向某个关系模型的名称,并且模型名称必须为英文小写。若A模型对B模型一对多,两个模型关联后,当查询模型A的某条数据时,可使用get_b_order()和set_b_order()来获取B的关联数据;可使用get_next_in_order()和get_previous_in_order()获取当前数据的上一条和下一条数据
- ordering: 属性值为列表,将模型数据以某个字段进行排序
- permissions: 属性值为元组,设置模型的访问权限,默认设置添加、修改和删除的权限
- proxy:若设置为True,则为模型创建代理模型,即为模块A克隆一个相同的模型B
- required_db_features:属性值为列表,声明模型依赖的数据库功能,如['gis_enabled'],表示模型依赖GIS功能
- required_db_vendor: 属性值为列表,声明模型依赖的数据库,默认支持SQLite、PostgreSQL、MySQL和Oracle
- select_on_save: 数据新增修改算法,通常无需设置,默认为False
- indexes: 属性值为列表,定义数据库表的索引列表
- verbos_name: 属性值为字符串,设置模型直观可读的名称并以复数形式表示
- verbos_name_plural: 与verbos_name相同,以单数形式表示
- label: 只读属性,属性值为app_label.object_name
- label_lower: 与label相同,但其值为字母小写
导数据
# 导出项目所有数据表
python manage.py dumpdata > data.json # 导出某个项目名称所有模型
python manage.py dumpdata index > data.json # 导出某个项目某个模型名称
python manage.py dumpdata index.PersonInfo > data.json # 导入数据
python manage.py loaddata data.json
三、数据表关系
# OneToOneField、ForeignKey、ManyToManyField
# 参数
- to: 必选参数,关联的模型名称
- on_delete: 必选参数,设置数据删除模式,删除模型包括:CASCADE/PROTECT/SET_NULL/SET_DEFAULT/SET/DO_NOTHING
- limit_choices_to: 设置外键的下拉选项,用于模型与表单和Admin后台系统
- related_name: 用于模型之间的关联查询,如反向查询
- related_query_name: 设置模型的查询名称,用于filter或get查询,若设置参数related_name则以该参数为默认值,若没有设置,则以模型名称的小写为默认值
- to_field: 设置外键与其他模型字段的关联性,默认关联主键,若要关联其他字段,则该字段必须具有唯一性
- db_constraint: 在数据库里是否创建外键约束,默认为true
- swappable: 设置关联模型的替换功能,默认为true,比如模型A关联模型B,想让模型C继承并替换B使得A与模型C之间关联
- symmetrical: 仅限于ManyToManyField,设置多对多字段之间的对称模式
- through: 仅限于ManyToManyField,设置自定义模型C,用于管理和创建模型A和B否多对多关系
- through_fields: 仅限于ManyToManyField,设置模型C的字段,确认模型C的哪些字段用于管理A和B否多对多关系
- db_table: 仅限于ManyToManyField,为管理和存储多对多关系的数据表设置表名称
四、数据查询
去重distinct
# 去重查询,distinct无需设置参数,去重方式根据values设置的字段执行
# SQL: select * from index_vocation where job='123';
v = Vocation.objects.values('job').filter(job='123').distinct()
聚合查询annotate、aggregate
# annotate类似sql里面的group by
# 如果不设置values,默认对主键进行group by分组
# SQL: select job, sum(id) as 'id__sum' from index_vocation group by job;
v = Vocation.objects.annotate(Sum('id')) # aggregate是计算某个字段的值并返回计算结果
# SQL: select count(id) as 'id__count' from index_vocation
v = Vocation.objects.aggregate(id_count=Count('id'))
结果集union、intersection、difference
# 每次查询的字段必须一致
v1 = Vocation.objects.filter(payment__gt=9000)
v2 = Vocation.objects.filter(payment__gt=5000) # 使用SQL UNION来组合两个或多个查询结果的并集
v1.union(v2) # 使用SQL INTERSECT来获取两个或多个查询结果的交集
v1.intersection(v2) # 使用SQL EXCEPT来获取两个或多个查询结果的差集
v2.difference(v2)
查询条件get:查询字段必须是主键或者唯一约束的字段,且查询的数据必须存在,否则程序会抛异常
查询条件filter:查询字段没有限制,只要该字段是数据表某一字即可。查询结果以列表形式返回,查询结果为空就返回空列表
多表查询select_related、prefetch_related
# select_related参数为字符串格式(外键字段related_name), 使用left outer join方式查询两个数据表
# 查询模型PersonInfo的name字段和模型Vocation的payment字段
p = PersonInfo.objects.select_related('personinfo').values('name', 'personinfo__payment') # select_related使用SQL的join实现的,对于多对多会增加数据查询时间和内存占用;prefetch_related更有优势
# 查询模型Program的某行数据
p = Program.objects.prefetch_related('performer').filter(name='123').first()
# 根据外键字段proformer获取当前数据的多对多或一对多关系
p.performer.all()
执行sql
# extra: 结果集修改器,一种提供额外查询参数的机制
# 查询job=123的数据
v = Vocation.objects.extra(where=['job=%s'], params=['123']) # 新增查询字段seat, select_params为selec的%s提供参数
v = Vocation.objects.extra(select={'seat': '%s'}, select_params=['seatInfo']) # raw
v = Vocation.objects.raw('select * from index_vocation')
v[0] # execute很容易受到sql注入攻击
from django.db import connection
cursor = connection.cursor()
cursor.execute('select * from index_vocation')
# 读取第一行数据
cursor.fetchone()
# 读取所有数据
cursor.fetchall()
迁移到不同数据库
# 在default数据库中创建数据表
python manage.py migrate # 在db1中创建数据表
python manage.py migrate --database=db1
五、数据库事务
事物是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行。
事物处理可以确保事务性单元内所有操作都成功完成,否则不会执行数据操作。
事物四大特性ACID:
- 原子性(Atomicity):一个事物是一个不可分割的工作单位,事物中包括的操作要么都做,要么都不做。
- 一致性(Consistency):事物必须使数据库从某个一致性状态到另一个一致性状态,一致性与原子性是密切相关的。
- 隔离性:一个事物的执行不能被其他事物干扰,即一个事物内部的操作及使用的数据对其他事物是隔离的,各个事物之间互不干扰。
- 持久性:也称永久性(Permanence),指一个事物一旦提交,它对数据库中数据的改变应该是永久性的,其他操作或故障不应该对其有任何影响。 # Django事物定义在django/db/transaction.py
- atomic(): 在视图函数或视图类使用事物
- savepoint(): 开启事物
- savepoint_rollback(): 回滚事物
- savepoint_save(): 提交事物
from django.shortcuts import render
from .models import *
from django.db import transaction
from django.db.models import F @transaction.atomic
def index(request):
# 开启事物保护
sid = transaction.savepoint()
try:
id = request.GET.get('id', '')
if id:
v = Vocation.objects.filter(id=id)
v.update(payment=F('payment') + 1)
print('Done')
# 提交事物
# 如不设置,当程序执行完成后,会自动提交事物
# transaction.savepoint_commit(sid)
else:
# 全表的payment字段自减1
Vocation.objects.update(payment=F('payment') - 1)
# 事物回滚,将全表payment字段自减1的操作撤回
transaction.savepoint_rollback(sid)
except Expection as e:
transaction.savepoint_rollback(sid) return render(request, 'index.html', local()) # 使用with模块实现
with transaction.atmonic():
pass
六、发送邮件
# 邮件配置信息
EMAIL_USE_SSL = True # Django与邮件服务器的连接方式是否设置ssl模式 # 邮件服务器,如果是163,就改成smtp.163.com
EMAIL_HOST = 'smtp.qq.com' # 设置服务器类型,qq邮箱分为SMTP和POP3服务器 # 邮件服务器端口
EMAIL_PORT = 465 # 若使用SMTP服务器,则端口应为465或587 # 发送邮件的账号
EMAIL_HOST_USER = '4512125@qq.com' # 账号必须开启POP3/SMTP服务 # SMTP服务密码
EMAIL_HOST_PASSWORD = 'SFSDDSFSVGSF' # 授权码 # 设置默认发送邮件的账号
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
Django Web应用开发实战第七章的更多相关文章
- Java Web整合开发实战:基于Struts 2+Hibernate+Spring 目录
第1篇 Java Web开发基础第1章 Web的工作机制( 教学视频:31分钟) 1.1 理解Web的概念 1.1.1 Web的定义 1.1.2 Web的三个核心标准 1.2 C/S与B/S两种软件体 ...
- 学习参考《Flask Web开发:基于Python的Web应用开发实战(第2版)》中文PDF+源代码
在学习python Web开发时,我们会选择使用Django.flask等框架. 在学习flask时,推荐学习看看<Flask Web开发:基于Python的Web应用开发实战(第2版)> ...
- Knockout应用开发指南 第七章:Mapping插件
原文:Knockout应用开发指南 第七章:Mapping插件 Mapping插件 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些 ...
- 微软实战训练营(X)重点班第(1)课:SOA必备知识之ASP.NET Web Service开发实战
微软实战训练营 上海交大(A)实验班.(X)重点班 内部课程资料 链接:http://pan.baidu.com/s/1jGsTjq2 password:0wmf <微软实战训练营(X)重点班第 ...
- Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序
Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后.C#的作用就发生了非常大的变化 ...
- Web前端开发实战6:CSS实现导航菜单结合二级下拉式菜单的简单变换
前面几篇博文都在讲导航菜单和二级下拉式菜单,事实上有非常多方法都能够实现的.详细的情况还要视情况而定. 在后面学习到jQuery框架之后,会有更丰富的动画效果.因为在学习Ajax和jQuery的初步阶 ...
- RxJava2实战---第七章 合并操作符和连接操作符
RxJava2实战---第七章 合并操作符和连接操作符 RxJava的合并操作符: startWith():在数据序列的开头增加一项数据. merge:将多个Observable合并为一个. merg ...
- [目录]ASP.NET web api开发实战
第一章:Restful web service v.s. RPC style web service 第二章:ASP.NET web api v.s. WCF v.s. ASP.NET web ser ...
- 2017.2.28 activiti实战--第七章--Spring容器集成应用实例(五)普通表单
学习资料:<Activiti实战> 第七章 Spring容器集成应用实例(五)普通表单 第六章中介绍了动态表单.外置表单.这里讲解第三种表单:普通表单. 普通表单的特点: 把表单内容写在 ...
- 2017.2.21 activiti实战--第七章--Activiti与spring集成(一)配置文件
学习资料:<Activiti实战> 第七章 Activiti与容器集成 本章讲解activiti-spring可以做的事情,如何与现有系统集成,包含bean的注入.统一事务管理等. 7.1 ...
随机推荐
- 【ABAQUS&Composite】composite layerup Manager从txt导入铺层信息
ABAQUS 在复合材料建模方面自由度是比较高的.官方提供了两个工具: ABAQUS/CAE中的Composite Layup Manager ABAQUS/CAE的plugin:Composites ...
- 如何编写Kubernetes的YAML(一)
什么是API对象 作为一个集群操作系统,Kubernetes 归纳总结了 Google 多年的经验,在理论层面抽象出了很多个概念,用来描述系统的管理运维工作,这些概念就叫做"API 对象&q ...
- composer remove 卸载依赖
remove 命令 remove 命令用于移除一个包及其依赖(在依赖没有被其他包使用的情况下),如果依赖被其他包使用,则无法移除: $ composer remove monolog/monolog ...
- 通过 JS 修改具体标签的属性的属性值
博客地址:https://www.cnblogs.com/zylyehuo/ window.addEventListener('DOMContentLoaded', function() { var ...
- docker clean images
docker ps | grep portal | awk '{print $2}' | cut -d ":" -f3 used=`docker ps | grep portal ...
- Ubuntu给Appimage创建快捷方式
下载 AppImageLauncher 2.安装 3.选择要运行的Appimage 双击运行即可.他会在home目录下创建一个applications文件夹,并且帮你自动创建快捷方式.
- EntityFrameworkCore 中实体的几种配置方法
使用数据注解 实体类通常是在Models目录下,直接在实体类上添加属性注解,比如[Required]/[Key]等. using System.ComponentModel.DataAnnotatio ...
- 老生再谈 IoC
IoC,Spring的核心理念之一,确实这是一个老生常谈的东西.但是今天呢!又重新温习之后,想再说说自己对IOC的一些想法. IoC--Inversion of Control,控制反转.要想理解Io ...
- IOC 中 bean 标签
- dify MCP工具调用
一.概述 前面几篇文章,介绍了Cherry Studio客户端调用MCP,接下来介绍dify如何调用MCP 二.dify插件 需要安装2个插件,分别是:Agent 策略(支持 MCP 工具),MCP ...