数据库:
是以一定方式存储在一起,能与多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合
数据库类型:
关系型数据库和非关系型数据库
MySQL服务管理:
启动MySQL服务:
net start mysql
停止MySQL服务:
net stop mysql
注意:
必须要有管理员权限才可以操作MySQL服务
MySQL操作:
操 作 命 令
创建一个数据库 create database [数据库名字];
删除一个数据库 drop database [数据库名字];
使用一个数据库 use [数据库名字];
查看当前数据库 select database();
查看所有数据库 show databases;
创建数据库并指定编码 create database [数据库名字] charset=‘utf8’;
修改数据库的编码 alter database [数据库名字] charset=‘gbk’;
MySQL常用数据类型:
1、整型
类型 范围 所占字节数
(1)tinyint -power(2,7)~power(2,7)-1 1
(2)smallint -power(2,15)~power(2,15)-1 2
(3)mediumint -power(2,23)~power(2,23)-1 3
(4)int -power(2,31)~power(2,31)-1 4
(5)bigint -power(2,63)~power(2,63)-1 8
2、定点数
decimal(m,d) # m总位数,d小数位
注意:
1、数字位数超过总长度m,就会对小数位进行四舍五入
2、数字小数位位数不足d,会自动用0填充
浮点数:
1、float(m,d) 具有8位精度
2、doulbe(m,n) 具有16位精度
注意:
浮点数指定保证最多8或16位的精确性,其余数字随即填充
3、字符串
类型 范围
char(n) 固定字符串长度(n,会保留n位,不足时会用空格填充)
varchar(n) 最大字符串长度(n)
4、日期
类型
datetime: YYYY-MM-DD HH:MM:SS
date: YYYY-MM-DD
time: HH:MM:SS
5、布尔(本质是tinyint)
类型 范围
boolean true|false
安装mysql的驱动:
python给mysql提供了4种驱动:
(1)MySQL-python(只支持python2.x)
(2)mysqlclient(建议安装: pip install mysqlclient)
(3)pymysql(建议安装: pip install pymysql)
(4)MySQL Connector
cmd登录MySQL:
(1)登录MySQL:
mysql -u root -p
然后会提示你输入密码:
>password:
(2)国内用户需要调整时区(从UTC改为Asia/Shanghai):
1、查看时区:
show variables like '%time_zone%'
2、设置时区:
set global time_zone="+8:00";
pycharm链接MySQL数据库:
点击pycharm右上角的database中的’+’,然后找到MySQL并创建
pycharm创建MySQL表结构:
create table [表名](
[字段名][字段类型][字段约束],
[字段名][字段类型][字段约束],
…
)
常用的字段约束:
约束类型 关键字
主键自增 primary key auto_increment
不能重复 unique
不能为空 not null
默认值 default
pycharm MySQL表结构查找数据:
(1)条件查询
查看所有数据
select * from [表名]
注意: *表示所有字段
查看指定数据
select [字段1],[字段2],... from [表名]
(2)比较条件查询
select * from [表名] where [条件]
条件 命令
相等 =
不相等 !=
为空 is null
不能为空 is not null
大于(大于等于) >(>=)
小于(小于等于) <(<=)
(3)模糊查询
select * from [表名] where [字段] like ""
关键字 说明
% 匹配任意多个字符
_ 匹配一个字符
(4)范围查询
select * from [表名] where [字段] in (可能性1,可能性2,...)
补充:
逻辑运算符
关键字 说明
and 并且
or 或
(5)分组
select * from [表名] where [条件] group by [字段1],[字段2],...
根据某字段进行分组
注意:
1、根据哪个字段进行分组,哪个字段就不会重复
2、group by 必须在where后面
补充:
cout(*) 用来返回group by后每个组的数量
例如:
select count(*),createTime from user group by createTime
对分组后数据进行筛选用having:
select * from [表名] where [条件] group by [字段] having [条件]
注意:
where是对select...from的结果进行数据筛选
having是对group by的结果进行筛选
(6)排序
select * from [表名] where [条件] group by [字段] having [条件] order by [字段1] asc|desc,[字段2] asc|desc,...
注意:
asc(默认):升序
desc:降序
(7)分页
select * from [表名] where [条件] group by [字段] having [条件] order by [字段] asc|desc limit [数据起始索引],[数据条数]
pycharm MySQL表结构增加数据:
插入一条数据:
insert into [表名] value ([数值1],[数值2],…)
向一些字段中插入一条数据:
insert into 表名 value ([数值1],[数值2],…)
插入多条数据:
insert into 表名 values ([数值1],[数值2],…),([数值1],[数值2],…),…
注意:
多条数据插入尽量用一条SQL语句
pycharm MySQL表结构删除数据:
delete from [表名] where [条件]
pycharm MySQL表结构修改数据:
update [表名] set [字段1]=[数值1],[字段2]=[数值2],…
pycharm MySQL表结构的更改:
关键字 说明
update 更改表内数据
alter table 更改表内结构
rename table 更改表名字
表内新增字段 alter table [表名] add [字段名][字段类型][字段约束]
表内修改字段 alter table [表名] change [原字段名] [字段名][字段类型][字段约束]
表内删除字段 alter table [表名] drop [字段名]
修改表的名字 rename table [原表名] to [新表名]
pycharm MySQL表结构的删除:
关键字 说明
delete 删除表内行数据
drop table 删除整个表,但可以回复
truncate 删除表内的所有数据,速度快,但不可以回复
drop table [表名] 删除表
truncate [表名] 删除表内全部数据
pycharm代码中使用MySQL数据库
在项目的settings.py中:
DATABASE = {
‘default’: {
‘ENGINE’: ‘django.db.backends.mysql’,
‘HOST’: ‘localhost’,
‘PORT’: 3306,
‘NAME’: ‘[使用的表的名字]’,
‘USER’: ‘[数据库的用户名]’,
‘PASSWORD’: ‘[数据库的用户密码]’,
}
}
pycharm MySQL表结构 创建表之间的关系:
1、一对多关系(用户和发帖,一个用户可以给发多个帖子,一个帖子只能由一个用过户发起)
create table user(
id int primary key auto_increment,
username varchar(16)
);
create table furum(
id int primary key auto_increment,
topic varchar(200),
user_id int,
constraint fu1 foreign key (user_id) references user(id) on delete CASCADE
);
注意:
constraint fu1 foreign key (user_id) references user(id) on delete CASCADE
constraint:约束
fu1:约束的名字(任意取)
references:引用
2、多对多关系(一个用户可以发多个帖子,一个帖子能被多个用户收藏)
create table user(
id int primary key auto_increment,
username varchar(16)
);
create table furum(
id int primary key auto_increment,
topic varchar(200),
user_id int,
constraint fu1 foreign key (user_id) references user(id) on delete CASCADE
);
中间表的创建:
create table middle(
form_id int,
user_id int,
constraint fu1 foreign key (form_id) references furum(id) on delete CASCADE
constraint fu2 foreign key (user_id) references user(id) on delete CASCADE
);
3、一对一关系(用户只能有一个用户信息详情页)
外键关系
级联类型 解释
on delete RESTRICT(默认)如果主表被引用的外键删除,会抛异常
on delete CASCADE 如果主表被引用的外键删除,相关联的表的记录也会被删除
on delete SETNULL 如果主表被引用的外键删除,相关联的表的记录会被设置为空
on delete NOACTION 如果主表被引用的外键删除,什么也不做
索引:
优化了数据库的查询
在相同情况下搜索一个字符串,运用索引建立整数关系比搜索字符串速度更快
建立索引:
create index [索引名] on [表名]([字段名]([索引长度]))
删除索引:
drop index [索引名] on [表名]
例如:
create index username_index on user(username(100))
drop index username_index on user
操作数据库:
1、使用原生sql语句:
在Django中使用原生sql语句,就是使用python.db.api的接口来操作
在app的views视图中:
from django.db import connection # django.db.connection代表默认的数据库连接
cursor = connection.cursor # connection.cursor()获取游标对象,使用数据库连接
cursor.execute(sql, [params]) #执行原生sql语句
例如:
cursor.execute("insert into user(name,age) value('Mike', 18)")
cursor.fetchone() # 返回表内查询结果后的一条数据
cursor.fetchall() # 返回表内查询结果后的所有数据
cursor.fetchmany(numbers) # 返回表内查询结果后的numbers条数据
案例:
图书馆管理系统
数据库的ORM模型(ORM,Object Relational Mapping,对象关系映射):
具有 易用性、吸能损耗小、设计灵活、可移植性 等特点
模型是有关数据的唯一确定的信息源。它包含要存储数据的基本字段和行为
通常,每个模型都映射到单个数据库表
1、每个模型都是django.db.models.Model或其的一个子类
2、模型的每个属性代表一个数据库字段。
from django.db import models
class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, null=False)
price = models.FloatField(null=False, default=0)
ORM数据库中常用字段:
1、AutoField
根据可用ID自动递增、
自动增长的整数类型(相当于auto_increament)
(1)常用参数primary_key=True
(2)如果没有另外指定,主键字段将自动添加到模型中
2、BigAutoField
一个64位整数,非常类似于AutoField
不同之处在于它保证可以匹配从1到的数字9223372036854775807(范围更大)
3、BigIntegerField
一个64位整数,非常类似于IntegerField
不同之处在于它保证可以匹配从-9223372036854775808到的 数字9223372036854775807(范围更大)
4、BinaryField
一个用于存储原始二进制数据的字段。它可以分配bytes, bytearray或memoryview。
默认情况下,BinaryField设置editable为False
在这种情况下,它不能包含在中ModelForm
BinaryField 有一个额外的可选参数:
BinaryField.max_length 字段的最大长度(以字符为单位)
最大长度在Django的验证(form表单验证)中使用强制执行 MaxLengthValidator。
注意以下情况属于滥用 BinaryField
将文件存储在数据库中
此字段不能代替适当的静态文件处理
5、BooleanField
True|False字段
在数据库层面是tinyint类型,默认值为None
在Django 2.1之前的版本中,此字段不允许null=True
因此您必须使用NullBooleanField
现在不建议使用后者
在Django 2.1之前的版本中,该字段blank=True是隐式的
6、CharField
字符串字段(类似于varchar),必须要传递参数max_length
ax_length在数据库级别和Django的验证中使用强制执行 MaxLengthValidator
对于大量文本,请使用TextField
7、DateField、TimeField、DateTimeField
首先区分两个概念:
navie time:不知道所显示的时间所代表的时区
aware time:知道所显示的时间所代表的时区
views.py中的代码:
from django.http import HttpResponse
from datetime import datetime
import pytz
# Create your views here.
def time_handler(request):
now = datetime.now() # datetime得到的是一个navie time
utc_timezone = pytz.timezone('UTC') # pytz.timezone('UTC') 设置当前时区为UTC时区
now.astimezone(utc_timezone) # 将navie time转换为aware time(仅在windows下不会报错)
注意:
在windows下运行没问题,因为系统会帮你自动把navie time 与loacal的时区一致
但在linux下运行会报错,因为now是navie time 没办法转换时区
print(now)
now.replace(tzinfo=pytz.timezone('Asia/Shanghai')) # 将navie time转换为aware time
print(now)
return HttpResponse(now)
pytz是python内置的一个时区包,里面有很多的时区
在项目settings.py中,
1、TIME_ZONE = 'Asia/Shanghai' USE_TZ = True
Django将会获取aware time
2、USE_TZ = False
Django将会获取navie time
from dango.utls.timezone import now
now()将会获取aware time(根据 USE_TZ = True 来判断获取时间类型)
from datetime.datetime import now
now()将会获取navie time
模板中更新时区:
(1)模板会自动根据项目settings.py中的TIME_ZONE = 'Asia/Shanghai' 设置时区
(2)使用load标签加载tz中的过滤器
{% load tz%}
{time| localtime} #localtime更改为当地时区
视图中更新时区:
from django.utls.timezone import localtime #会根据settings.py中TIME_ZONE设置时区
DateField
日期类型,有一些额外的可选参数:
DateField.auto_now
每次保存对象时自动将字段设置为当前时间(即最后一次修改的时间戳)
注意:
该参数始终使用当前日期
该字段仅在调用Model.save()时自动更新
以其他方式(例如QuerySet.update())对其他字段进行更新时该字段不会更新
DateField.auto_now_add
首次创建对象时,将字段自动设置为当前时间(即第一次创建的时间戳)
注意:
该参数始终使用第一次创建日期
如果希望能够修改此字段,请设置以下内容,而不是 auto_now_add=True:
1、对于DateField字段:
default=date.today(函数原型 datetime.date.today())
2、对于DateTimeField字段:
default=timezone.now(函数原型 django.utils.timezone.now())
补充:
选项auto_now_add,auto_now和default是互斥的
这些选项的任何组合都将导致错误。
提醒:
如果设置了auto_now或auto_now_add为True会导致该字段的其他参数发生变化:
editable=False blank=True
注意:
auto_now和auto_now_add选项将始终使用创建或更新时默认时区中的日期
如果需要不同的方法,可以考虑使用自己的可调用默认值或重写save()
而不是使用auto_now或auto_now_add为True
或者使用datetime字段而不是DateField并决定如何在显示时处理从datetime到date的转换
DateTimeFiel
日期和时间类型,接受与DateField相同的额外参数
TimeField
时间类型,接受与DateField相同的自动填充选项
8、DecimalField
固定精度的十进制数字,他的表单验证输入是DecimalValidator
有两个必要参数:
DecimalField.max_digits 最大位数
DecimalField.decimal_place 小数存储位数
9、DurationField
一个存储时间段的字段
注意:
DurationField在大多数情况下都可以算术运算(除了在PostgreSQL)
10、EmailField
类似于CharField,用来上传Email,会在表单验证是验证是否是有效的email地址EmailValidator
11、FileField
类似于CharFieldm默认最大长度为100个字符,用来存储File
注意:
primary_key不支持该参数
有两个可选参数:
1、FileField.upload_to 此属性提供了一种设置上传目录和文件名的方法,将值传递给该 Storage.save()方法
(1)如果指定一个可能包含strftime()格式的字符串值,
例如:upload = models.FileField(upload_to='uploads/%Y/%m/%d/')该格式将被文件上载的日期/时间替换
(2)如果使用默认值 FileSystemStorage则将字符串值添加到MEDIA_ROOT路径中
以形成本地文件系统上将存储上传文件的位置
例如:upload = models.FileField(upload_to='uploads/')
upload_to也可以是可调用的数据类型,例如函数,用以获得获得上载路径(包括文件名)
该可调用对象必须接受两个参数,并返回要传递给存储系统的Unix样式的路径(带有正斜杠):
参数 描述
instance FileField定义的模型实例
在大多数情况下,这个对象将不会被保存到数据库中
filename 最初提供给文件的文件名
例如:
def file_path(instance, filename):
return 'user_{}/{}'.format(instance.user.id, filename)
class FileStoreModel(models.Model):
upload = models.FileField(upload_to=file_path)
2、FileField.storage
一个存储对象,用于处理文件的存储和检索
在模型中使用FileField或ImageField需要执行几个步骤:
(1)在项目的settings.py文件中,指定MEDIA_ROOT为存储上传文件的目录的完整路径
例如:
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
注意:
指定了MEDIA_ROOT就是可以不指定upload_to
为了提高性能,这些文件未存储在数据库中
(2)定义MEDIA_URL为该目录的基本公共URL
确保该目录可由Web服务器的用户读取和写入文件
存储在数据库中的所有内容都是指向文件的路径,如果希望使用Django提供的便利url属性去访问
例如:
存储的ImageField的filename=mug_shot,则可以使用{{object.mug_shot目标.url}}
如果要检索上载的文件在磁盘上的文件名或文件的大小,可以分别使用name和size属性
注意:
该文件被保存为在数据库中保存模型的一部分,因此在保存模型之前,不能依赖磁盘上使用的实际文件名
无论何时处理上传的文件,都应密切注意上传文件的位置以及文件的类型,以避免安全漏洞
因为上传的HTML文件也可以由浏览器执行,它也可能构成XSS或CSRF攻击的安全威胁。
所以验证所有上载的文件,以确保文件符合您的想法
12、FileField和FieldFile
当访问FileField模型时,系统会为您提供实例FieldFile作为代理,用于访问基础文件
FieldFile的API反映了的API File
但有一个主要区别:
类包装的对象不一定是Python内置文件对象的包装
相反,是Storage.open() 方法结果的包装,它可以是File对象,也可以是FileAPI 的自定义存储的实现
警告:
此类save()和的delete()两种方法默认将关联的FieldFile模型对象保存在数据库中
除了从File诸如write()、read()和继承的API之外,FieldFile还包括几种可用于与基础文件进行交互的方法:
(1)FieldFile.name
文件名
(2)FieldFile.size
文件的大小
(3)FieldFile.url
通过调用url()——Storage类的基础方法 来访问文件的相对URL
(4)FieldFile.open(mode ='rb')
在指定的中打开或重新打开与此实例关联的文件 mode
注意:
由于在访问基础文件时会隐式打开基础文件,因此可能无需调用此方法,除非将指针重置为基础文件或更改mode。
(5)FieldFile.close
行为类似于标准的Python file.close()方法,并关闭与此实例关联的文件
(6)FieldFile.save(name,content,save = True)
此方法将文件名和文件内容传递到该字段的存储类,然后将存储的文件与model字段关联
接受两个必需的参数:
name这是文件的名称
content是包含文件内容的对象
save可选参数,控制在更改与该字段关联的文件之后是否保存模型实例,默认为 True。
注意:
content参数应该是django.core.files.File实例
而不是Python的内置文件对象
可以File像这样从现有的Python文件对象构造一个:
(1) from django.core.files import File
f = open('/path/to/hello.world')
myfile = File(f)
(2)from django.core.files.base import ContentFile
myfile = ContentFile("hello world")
(7)FieldFile.delete(save = True)
删除与此实例关联的文件,并清除字段上的所有属性。
save可选,参数控制在删除与该字段关联的文件之后是否保存模型实例,默认为 True。
注意:
如果在delete()调用时碰巧打开了文件,此方法将关闭文件 。
删除模型时,不会删除相关文件,如果需要清理孤立的文,则需要自己处理
13、FilePathField
类似于harField,其选择仅限于文件系统上某个目录中的文件名
具有三个特殊参数,其中第一个参数是必需的:
(1)FilePathField.path
目录的绝对文件系统路径,从中可以FilePathField选择该目录
(2)FilePathField.match
作为字符串的正则表达式,FilePathField 将用于过滤文件名
注意:
正则表达式将应用于基本文件名,而不是完整路径。
(3)FilePathField.recursive
默认值为False,指定是否path应包含的所有子目录
(4)FilePathField.allow_files
默认值为True。指定是否应包含指定位置的文件
如果是allow_files=True,那么allow_folders=True
(5)FilePathField.allow_folders
默认值为False。指定是否应包含指定位置的文件夹
如果是allow_folders=True,那么allow_files=True
当然,这些参数可以一起使用。
FilePathField(path="/home/images", match="foo.*", recursive=True)
14、FloatField
由float实例表示的浮点数。
有两个必要参数:
FloatField.max_digits 最大位数
FloatField.decimal_place 小数存储位数
15、ImageField
从继承所有属性和方法FileField,还验证上载的对象是有效的图像
除了可用于特殊属性FileField,一个ImageField也具有height和width属性
为了便于查询这些属性,ImageField有两个额外的可选参数:
(1)ImageField.height_field
每次保存模型实例时,模型字段的名称都会自动填充图像的高度。
(2)ImageField.width_field
每次保存模型实例时,模型字段的名称都会自动填充图像的宽度。
使用该字段需要安装pillow库(pip install pillow)
16、IntegerField
一个整数
从-2147483648到2147483647的值在Django支持的所有数据库中都是安全的。
17、GenericIPAddressField
字符串格式的IPv4或IPv6地址
(1)GenericIPAddressField.protocol
将有效输入限制为指定的协议。可接受的值为'both'(默认值)、'IPv4' 或'IPv6'
(2)GenericIPAddressField.unpack_ipv4
解压缩IPv4映射的地址
例如:
ffff:192.0.2.1如果启用此选项,则该地址将被解压缩到 192.0.2.1
默认设置为禁用。只能在protocol设为时使用'both'。
18、NullBooleanField
使用NullBooleanField代替BooleanField(null=True)
19、PositiveIntegerField
类似于IntegerField,非负整数
从0到2147483647的值在Django支持的所有数据库中都是安全的。0出于向后兼容的原因,接受该值
20、PositiveSmallIntegerField
类似于PositiveIntegerField,非负整数
从0到32767的值在Django支持的所有数据库中都是安全的
21、SlugField
slug是某事物的短标签,只包含字母、数字、下划线或连字符,它们通常用在url中
SlugField.allow_unicode
如果为True,则该字段除了接受ASCII字母外,还接受Unicode字母。默认为False。
22、SmallIntegerField
类似于IntegerField,
从-32768到32767的值在Django支持的所有数据库中都是安全的。
23、TextField
大文本字段
24、URLField
一个CharField一个URL,通过表单提交验证URLValidator。
25、UIDField
用于存储通用唯一标识符的字段。使用Python的 UUID类
UIDField是通用的唯一标识符AutoFieldfor的很好替代,该数据库不会为您生成UUID,因此建议使用default
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
ORM数据库中常用的约束字段:
关键字 说明 默认值
null 在数据库中存储是否为空 False
primary_key 是否是主键 False
blank 在Django后台管理新增或编译一条数据时是否能为空 False
db_column 字段在表中所显示的名字 属性名
default 字段的默认值
unique 能否重复,是否唯一 False
外键和表的关系:
在MySQL中有两种引擎,一种是InnoDB(支持外键约束),另一种是myisam
关系字段
1、ForeignKey
多对一关系
需要两个位置参数:
(1)to:
与模型相关的类,如果相对应的引用模型不在同一个app内,则要填写完整路径
(2)on_delete:
引用模型类的外键约束(当ForeignKey删除由a引用的对象时,Django将模拟on_delete参数指定的SQL约束的行为 )
(3)related_name:
两张表之间存在某种关系时,用于反向引用
如果不声明related_name,也可以使用[表名]+_set进行反向引用
注意:
要创建递归关系(一个与自身具有多对一关系的对象)
例如:
特工的代号和特工本身
请使用models.ForeignKey('self', on_delete=models.CASCADE)
models.py中的代码:
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=20)
class Books(models.Model):
book_name = models.CharField(max_length=100)
price = models.FloatField(default=0)
author = models.ForeignKey(to='User', on_delete=models.CASCADE, related_name='user')
ForeignKey.on_delete
当ForeignKey删除由a引用的对象时,Django将模拟on_delete参数指定的SQL约束的行为
参数值为:
(1)CASCADE
级联删除
删除包含ForeignKey的对象。
(2)PROTECT
通过引发ProtectedError的子类django.db.IntegrityError来 防止删除引用的对象(抛出异常)
(3)SET_NULL
将引用的对象设置为ForeignKey为null
(4)SET_DEFAULT
将ForeignKey其设置为默认值
ForeignKey必须设置默认值
例如上面的代码中:
author = models.ForeignKey(to='User', on_delete=models.SET_DEFAULT, related_name='user')
则在User表中必须设置默认值
(5)SET(表达式)
将设置为ForeignKey传递给的值SET()或者如果传递了callable,则调用它的结果
(6)DO_NOTHING
不采取行动
外键参数:
1、ForeignKey.limit_choices_to
当使用ModelForm或admin呈现此字段时,
为该字段的可用选项设置限制(默认情况下,查询集中的所有对象都可供选择)
可以使用dictionary、Q对象或返回dictionary或Q对象的callable
例如:
staff_member = models.ForeignKey(User,on_delete=models.CASCADE,limit_choices_to={'is_staff': True},)
导致上的相应字段ModelForm仅列出Users具有的字段is_staff=True
如果将“选项”限制为“是”或返回一个Q对象,这对于复杂的查询很有用,
则只有当该字段未列在模型的ModelAdmin的“原始”字段中时,它才会对管理中可用的选项产生影响
注意:
如果将callable用于limit_choices_to,则每次实例化新表单时都会调用它
当验证模型时也可以调用它
2、ForeignKey.related_name
用于从相关对象到此对象的关系的名称
它也是related_query_name(用于目标模型的反向过滤器名称的名称)的默认值
如果您希望Django不要创建反向关系,请将设置 related_name为'+'或以结束'+'
例如:
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='+',
)
3、ForeignKey.related_query_name
用于目标模型的反向过滤器名称的名称
默认为related_name或default_related_name的值,否则默认为模型的名称:
例如:
models.py中的代码:
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=20)
class Books(models.Model):
book_name = models.CharField(max_length=100)
price = models.FloatField(default=0)
author = models.ForeignKey(to='User', on_delete=models.CASCADE, related_name='user')
views.py中的代码:
from django.http import HttpResponse
from .models import Books, User
# Create your views here.
def index_handler(request):
user = User.objects.filter(user__book_name="西游记").first()
print(user.username)
return HttpResponse('success')
4、ForeignKey.to_field
关系所关联的相关对象上的字段
默认情况下,Django使用相关对象的主键
如果您引用其他字段,则该字段必须具有unique=True。
5、ForeignKey.db_constraint
控制是否应在数据库中为此外键创建约束
默认值为True
在某些情况下,您可能需要执行以下操作:
您有无效的旧数据
您正在数据库分类
如果将其设置为False,则访问不存在的相关对象将引发其DoesNotExist异常。
6、ForeignKey.swappable
如果ForeignKey指向可交换模型,则控制迁移框架的反应
如果它是True(默认值),ForeignKey则指向与当前值settings.AUTH_USER_MODEL(或另一个可交换模型设置)匹配的模型,
该关系将使用对设置的引用(而不是直接指向模型)存储在迁移中。
仅当您确定模型始终指向交换的模型时(例如,如果它是专门为自定义用户模型设计的配置文件模型),才需要覆盖此设置。
如有疑问,请将其保留为默认值True。
2、ManyToManyField
多对多关系。
需要一个位置参数:
与模型相关的类
models.py中的代码:
class Collection(models.Model):
name = models.CharField(max_length=200)
aticles = models.ManyToMany("Artucle")
class Article(models.Model):
article_name = models.CharField(max_length=200)
views.py中的代码:
article = Article(article_name='hot') 1
collection = Collection(name='hot_topic') 2
collection.articles.add(article) 3
collection.save()
注意此时代码会报错,因为语句1未保存到数据库中
解决方案:
1、在语句1后插入article.save()
2、在语句3中的add方法中插入一个bulk属性
例如:
collection.articles.add(article, bulk=False)
注意:
bulk不适合在多对多关系中使用
其工作原理与之完全相同 ForeignKey,包括递归和 惰性关系。
参数:
ManyToManyField 接受一组额外的参数(所有可选参数),这些参数控制关系的功能。
(1)ManyToManyField.related_name
与相同ForeignKey.related_name
(2)ManyToManyField.related_query_name
与相同ForeignKey.related_query_name
(3)ManyToManyField.limit_choices_to
与相同ForeignKey.limit_choices_to
(4)ManyToManyField.symmetrical
仅用于对self的ManyToManyFields的定义(递归)
考虑以下模型:
from django.db import models
class Person(models.Model):
friends = models.ManyToManyField("self")
当Django处理这个模型时,它标识它本身有一个ManyToManyField,因此,它不会向person类添加person_set属性
相反,ManyToManyField被假定为对称的——也就是说,如果我是你的朋友,那么你就是我的朋友。
如果不希望在与self的多对多关系中对称,则将symmetrical设置为Fasle
(5)ManyToManyField.through
Django会自动生成一个中间表来管理多对多关系
但是,如果要手动指定中间表,则可以使用该through选项来指定表示要使用的中间表的Django模型。
此选项最常见的用法是当您要将多余的数据与多对多关联相关联时 。
如果未指定显式through模型,则仍然可以使用隐式模型类直接访问为保存关联而创建的表。它具有三个用于链接模型的字段。
如果源模型和目标模型不同,那么将生成以下字段:
id:关系的主键。
<containing_model>_id:id声明的ManyToManyField模型
<other_model>_id:指向id的ManyToManyField模型
如果ManyToManyField指向和指向同一模型的点相同,则会生成以下字段:
id:关系的主键。
from_<model>_id:id指向模型的实例(即源实例)的。
to_<model>_id:id关系所指向的实例的实例(即目标模型实例)。
(6)ManyToManyField.through_fields
仅在指定自定义中间表模型时使用
Django通常会确定要使用中介模型的哪些字段,以便自动建立多对多关系
请考虑以下模型:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=50)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
)
class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
Membership对Person有两个外键(Person和inviter),这使得关系模糊不清,Django无法知道使用哪一个
在这种情况下,您必须使用明确指定Django应该使用的外键
如上例所示:
through_fields=('group', 'person')
through_fields接受一个2元组('field1','field2')
field1是ManyToManyField在其上定义的模型的外键的名称(在本例中是group)
field2是目标模型外键的名称(本例中是person)
当中间表模型上有多个外键指向参与多对多关系的任何模型(甚至两者)时,必须指定through_field
当使用中间表模型并且模型有两个以上的外键时,或希望显式指定应该使用哪两个字段时,这也适用于递归关系
(7)ManyToManyField.db_table
为存储多对多数据而创建的表的名称
如果未提供,则Django将基于以下名称采用默认名称:定义关系的模型表和字段本身的名称
(8)ManyToManyField.db_constraint
控制是否应在数据库中为中间表中的外键创建约束
默认值为True,在某些情况下,您可能需要执行以下操作:
您有无效的旧数据。
您正在分片数据库。
同时传递db_constraint和和是错误的through。
(9)ManyToManyField.swappable
如果它ManyToManyField 指向可交换模型,则控制迁移框架的反应。
如果它是True默认值,ManyToManyField则指向与当前值settings.AUTH_USER_MODEL(或另一个可交换模型设置)匹配的模型,该关系将使用对设置的引用(而不是直接指向模型)存储在迁移中。
仅当您确定模型始终指向交换的模型时(例如,如果它是专门为自定义用户模型设计的配置文件模型),才需要覆盖此设置。
如有疑问,请将其保留为默认值True
注意:
ManyToManyField不支持validators。
null 没有作用,因为没有办法在数据库级别上要求关联。
3、OneToOneField
一对一的关系
需要一个位置参数:
与模型相关的类
它的工作原理与之完全相同ForeignKey,包括有关递归 和惰性关系的所有选项。
如果您未指定的related_name参数,则 OneToOneFieldDjango将使用当前模型的小写名称作为默认值。
此外,OneToOneField接受接受的所有其他参数ForeignKey,再加上一个参数:
OneToOneField.parent_link
当True在从另一个具体模型继承的 模型中使用时,指示该字段应该用作返回父类的链接,
而不是OneToOneField通常由子类隐式创建的多余 部分
模型中Meta的配置
对于一些模型级别的配置,我们可以在模型中定义一个Meta类,然后在这个类中加一些属性来控制模型
class Book(models.Model):
name = models.CharField(max_length=200)
class Meta:
db_table =’’ # 模型迁移映射到数据库以后所显示的表单的名字
ordering = [’’,…] # 根据类表中的字段对表单中的数据进行排序(默认时升序,在字段名前面加个’-'变成降序)