我的Django学习笔记(6)MySQL数据库链接,模型类

数据库:
是以一定方式存储在一起,能与多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合

数据库类型:
	关系型数据库和非关系型数据库

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 = [’’,…] # 根据类表中的字段对表单中的数据进行排序(默认时升序,在字段名前面加个’-'变成降序)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值