内容概要
查询关键字
1 2 3 4 5 6 7 8 9 10 11 12 MySQL select from where group by having order by distinct limit regexp Django ORM
神奇的双下线查询
多表查询
1 2 3 4 5 子查询 基于对象的跨表查询 连表操作 基于双下划线的跨表查询 ps:ORM远比SQL语句简单
分组与聚合
F与Q查询
ORM查询优化(only与defer…)
ORM字段补充
内容详细 关键字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
神奇的双下划线 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
外键字段增删改查 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
重要概念 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 """ 正向查询 反向查询 当前查询对象是否含有外键字段 如果有就是正向 没有无则是反向 口诀: 正向查询按外键字段 多对多需要额外再加一个.all() 一对多和一对一不需要加 反向查询按表名小写 一对多与多对多 _set.all() 一对一 不需要加 """
多表查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
F查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from django.db.models import F'''针对字符串不能直接拼接 需要额外导入模块操作'''
Q查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 '''filter()括号内可以写多个参数 逗号隔开 默认只支持and连接''' from django.db.models import Q'''Q进阶用法''' q = Q() q.connector = 'or' q.children.append(('title__contains' ,'三' )) q.children.append(('price__gt' ,200 )) res = models.Book.objects.filter (q) print (res)print (res.query)
事务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 """ 1.事务四大特性 ACID 原子性 一致性 独立性 持久性 2.数据库设计三大范式 课下百度搜索自己概括 MySQL start transcation commit rollback """ from django.db import transaction try : with transaction.atomic(): models.Order.objects.create(num="110110111" , product_id=1 , count=1 ) models.Product.objects.filter (id =1 ).update(kucun=F("kucun" ) - 1 , maichu=F("maichu" ) + 1 ) except Exception as e: print (e)
执行原生SQL语句 1 2 3 4 res = models.Book.objects.raw('select * from app01_book' ) for i in res: print (i)
模型层字段及参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 models.AutoField(primary_key=True ) models.CharField(max_length=32 ) models.IntergeField() models.DateField() models.DateTimeField() auto_now auto_now_add models.DecimalField() models.BooleanField() 给这个字段传布尔值会自动转换成数字0 或1 一般用在状态二选一 TextField() 存储大段文本(bbs项目会使用) EmailField() 存储邮箱格式数据 FileField() 存储数据路径(bbs项目会使用) """自定义字段""" from django.db.models import Fieldclass MyCharField (Field ): def __init__ (self,max_length,*args,**kwargs ): self.max_length = max_length super ().__init__(max_length=max_length,*args,**kwargs) def db_type (self, connection ): return 'char(%s)' %self.max_length
常见参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 max_length varbose_name default null auto_now auto_now_add to unique db_index choices 创建用户表 性别 两到三种状态 学历 也是有限个 在职状态 也是有限个 婚姻 也是有限个 ... """针对某个字段可以列举完全的情况 一般都是使用choices参数""" class Server (models.Model ): host = models.CharField(max_length=32 ) status_choices = ( (1 ,'在线' ), (2 ,'待上线' ), (3 ,'宕机' ), (4 ,'待上架' ) ) status = models.IntegerField(choices=status_choices) desc_choices = ( ('哈哈' ,'哈哈哈哈哈哈' ), ('呵呵' ,'呵呵呵呵呵呵' ), ('嘿嘿' ,'嘿嘿嘿嘿嘿嘿' ), ('嘻嘻' ,'嘻嘻嘻嘻嘻嘻' ), ) desc = models.CharField(max_length=32 ,choices=desc_choices) .get_字段名_display()
ORM查询优化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 用不到的数据即使写了orm语句也不会执行 1. only与defer2. select_related与prefech_related """ only括号内写什么字段 生成的对象就含有对应的属性 在查找该属性的时候不再走数据库查询 但是一旦查找括号内没有的字段属性 则每次都会走数据库查询 """ """ defer与only刚好相反 生成的对象就不含有对应的属性 在查找该属性的时候需要每次走数据库查询 但是一旦查找括号内没有的字段属性 则不需要走数据库查询 """ """ select_related相当于连表操作 先将models后面的表和括号内外键字段关联的表连接起来 之后一次性把所有的数据封装到数据对象中 """ res = models.Book.objects.prefetch_related('publish' ) for i in res: print (i.publish.title) """ prefetch_related相当于子查询 先查询models后面的表的所有的数据 然后将括号内关联的表的数据全部查询出来 之后整合到一起 """
常用及非常用字段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 AutoField(Field) - int 自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id 的列 from django.db import modelsclass UserInfo (models.Model ):username = models.CharField(max_length=32 ) class Group (models.Model ):nid = models.AutoField(primary_key=True ) name = models.CharField(max_length=32 ) SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both' ,"ipv4" ,"ipv6" unpack_ipv4, 如果指定为True ,则输入::ffff:192.0 .2 .1 时候,可解析为192.0 .2 .1 ,开启此功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None , 正则匹配 recursive=False , 递归下面的文件夹 allow_files=True , 允许文件 allow_folders=False , 允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None , 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10 进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型
对应关系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 对应关系: 'AutoField' : 'integer AUTO_INCREMENT' , 'BigAutoField' : 'bigint AUTO_INCREMENT' , 'BinaryField' : 'longblob' , 'BooleanField' : 'bool' , 'CharField' : 'varchar(%(max_length)s)' , 'CommaSeparatedIntegerField' : 'varchar(%(max_length)s)' , 'DateField' : 'date' , 'DateTimeField' : 'datetime' , 'DecimalField' : 'numeric(%(max_digits)s, %(decimal_places)s)' , 'DurationField' : 'bigint' , 'FileField' : 'varchar(%(max_length)s)' , 'FilePathField' : 'varchar(%(max_length)s)' , 'FloatField' : 'double precision' , 'IntegerField' : 'integer' , 'BigIntegerField' : 'bigint' , 'IPAddressField' : 'char(15)' , 'GenericIPAddressField' : 'char(39)' , 'NullBooleanField' : 'bool' , 'OneToOneField' : 'integer' , 'PositiveIntegerField' : 'integer UNSIGNED' , 'PositiveSmallIntegerField' : 'smallint UNSIGNED' , 'SlugField' : 'varchar(%(max_length)s)' , 'SmallIntegerField' : 'smallint' , 'TextField' : 'longtext' , 'TimeField' : 'time' , 'UUIDField' : 'char(32)' ,
ORM字段参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 用于表示某个字段可以为空。 如果设置为unique=True 则该字段在此表中必须是唯一的 。 如果db_index=True 则代表着为此字段设置索引。 为该字段设置默认值。 配置auto_now_add=True ,创建数据记录的时候会把当前时间添加到数据库。 配置上auto_now=True ,每次更新数据记录的时候会更新该字段。 null 数据库中字段是否可以为空 db_column 数据库中字段的列名 db_tablespace default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices=[(0 , '何穗' ),(1 , '大表姐' ),],default=1 ) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null' : "不能为空." , 'invalid' : '格式错误' } validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidatorfrom django.core.validators import EmailValidator,URLValidator,DecimalValidator,\MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32 , error_messages={ 'c1' : '优先错信息1' ,'c2' : '优先错信息2' ,'c3' : '优先错信息3' ,}, validators=[ RegexValidator(regex='root_\d+' , message='错误了' , code='c1' ), RegexValidator(regex='root_112233\d+' , message='又错误了' , code='c2' ), EmailValidator(message='又错误了' , code='c3' ), ] )
关系字段 ForeignKey 外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 ‘一对多’中’多’的一方。
ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。
to 设置要关联的表
to_field 设置要关联的表的字段
反向操作时,使用的字段名,用于代替原反向查询时的’表名_set’。
例如:
1 2 3 4 5 6 class Classes (models.Model ): name = models.CharField(max_length=32 ) class Student (models.Model ): name = models.CharField(max_length=32 ) theclass = models.ForeignKey(to="Classes" )
当我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写:
1 models.Classes.objects.first().student_set.all ()
当我们在ForeignKey字段中添加了参数 related_name 后,
1 2 3 class Student (models.Model ): name = models.CharField(max_length=32 ) theclass = models.ForeignKey(to="Classes" , related_name="students" )
当我们要查询某个班级关联的所有学生(反向查询)时,我们会这么写:
1 models.Classes.objects.first().students.all ()
反向查询操作时,使用的连接前缀,用于替换表名。
on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。
models.CASCADE 删除关联数据,与之关联也删除
models.DO_NOTHING 删除关联数据,引发错误IntegrityError
models.PROTECT 删除关联数据,引发错误ProtectedError
models.SET_NULL 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
1 2 3 4 5 6 7 8 9 def func (): return 10 class MyModel (models.Model ): user = models.ForeignKey( to="User" , to_field="id" , on_delete=models.SET(func) )
db_constraint 是否在数据库中创建外键约束,默认为True。
OneToOneField 一对一字段。
通常一对一字段用来扩展已有字段。
一对一的关联关系多用在当一张表的不同字段查询频次差距过大的情况下,将本可以存储在一张表的字段拆开放置在两张表中,然后将两张表建立一对一的关联关系。
1 2 3 4 5 6 7 8 class Author (models.Model ): name = models.CharField(max_length=32 ) info = models.OneToOneField(to='AuthorInfo' ) class AuthorInfo (models.Model ): phone = models.CharField(max_length=11 ) email = models.EmailField()
to 设置要关联的表。
to_field 设置要关联的字段。
on_delete 同ForeignKey字段。
ManyToManyField 用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系
to 设置要关联的表
同ForeignKey字段。
同ForeignKey字段。
symmetrical 仅用于多对多自关联时,指定内部是否创建反向操作的字段。默认为True。
举个例子:
1 2 3 class Person (models.Model ): name = models.CharField(max_length=16 ) friends = models.ManyToManyField("self" )
此时,person对象就没有person_set属性。
1 2 3 class Person (models.Model ): name = models.CharField(max_length=16 ) friends = models.ManyToManyField("self" , symmetrical=False )
此时,person对象现在就可以使用person_set属性进行反向查询。
through 在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。
但我们也可以手动创建第三张表来管理多对多关系,此时就需要通过through来指定第三张表的表名。
through_fields 设置关联的字段。
db_table 默认创建第三张表时,数据库中表的名称。