day56_9_20orm中的关键字段,orm查询13方法整合,查询优化和事务
一。常用字段。 在orm中有一些字段是常用字段: 1.AutoField 这个字段是自增的,必须填入参数primary_key=True,也就是说这个字段是表的主键,如果表类中没有自增列,就会自动创建名为id的自增列。 2.IntegerField 是一个整数类型,范围在?-2147483648到 2147483647。但是一般不用它来存储手机号,位数不够。 3.DateField。 这是日期字段,也就是YYYY-MM-DD,相当于Python中的datetime。date()实例。 4.DateTimeField 与3字段不同的是,这个字段会添加时分秒参数,像YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。(auto_now,auto_now_add) 5.BooleanField 布尔类型参数,给该字段传值的时候,你只需要传递布尔值即可,但是对应到数据库就会传递0或者1. 6.TextField 文本类型字段,用来传递大型的文本。 7.FileField 文件字段。字符串类型,路径保存在数据库,文件上传到指定的目录。 他的参数有upload_to=‘‘file/‘‘,用户上传的文件会自动放到等号后面指定字段的文件路径中(在项目文件下。) storage = None? ?存储组件,默认django.core.files.storage.FileSystemStorage 8.CharField 字符类型,这个类型必须提供max_length参数,代表这个字符的长度 9.自定义char字段, 在django中,字符串型式的都是varchar类型的文件,我们可以通过自定义的方式来定义一个。 class MyChar(models.Field): def __init__(self,max_length,*args,**kwargs): self.max_length = max_length super().__init__(max_length=max_length,**kwargs) def db_type(self,connection): return ‘char(%s)‘%self.max_length #返回char类型。 其他字段: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列 from django.db import models class UserInfo(models.Model): # 自动创建一个列名为id的且为自增的整数列 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) - 二进制类型 字段合集 字段与sql语句对应: 对应关系: ‘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字段与MySQL字段对应关系 字段对应的参数 字段中也需要一些参数设置。 1.null 表示某个字段可以为空。添加字段时使用。 2.unique 可以设置其是唯一值。unique=True,设置1对一时可以使用foreign+unique 3.db_index 如果db_index=True时,代表这为字段设置索引。注意查询效率。 4.default。 为该字段设置默认值。 5.时间字段专用。 auto_now_add: 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库 auto_now: 配置auto_now=True,每次更新数据记录的时候会更新该字段。 二。关系字段: 1.foreignkey 外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 ‘一对多‘中‘多‘的一方。 ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。 字段参数 1.to 设置其关联的表 2.to_field 设置要关联的表的字段,如果不设置则会自动关联外键。 3.on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。(级联删除) 参数值:models.CASCADE 4.db_constraint 是否在数据库中创建外键约束。默认为True.也就是级联操作。 其他的关联动作: models.DO_NOTHING
删除关联数据,引发错误IntegrityError
models.PROTECT
删除关联数据,引发错误ProtectedError
models.SET_NULL
删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT
删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET
删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User",to_field="id", on_delete=models.SET(func) ) Django2中所需要添加的参数: 当你在使用django2.X版本的时候 在建立外键关系时(*****),需要你手动添加几个关键点参数。 models.cascade db_constraints 2.onetoonefield 可以通过foreignField(unique=Ture)来设置。 字段参数:to,to_field,on_delete。 三。总结13个查询操作。 可与上上篇博客参考: (1)?all(): 查询所有结果 (2)filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 (3)get(**kwargs):返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象) (4)exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 (5) order_by(*field): 对查询结果排序(‘-id‘) / (‘price‘) (6) reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向 (7) count(): 返回数据库中匹配查询(QuerySet) (8) first(): 返回第一条记录print(models.Book.objects.filter(pk=1).first()) (9) last(): 返回最后一条记录 ? (10) exists(): 如果QuerySet包含数据,就返回True,否则返回False (11)values(*field):返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列. (12)values_list(*field):它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列. (13)distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。) 其中,返回的是QuerySet对象的方法有: all() filter() exclude() order_by() reverse() distinct() 返回特殊的QuerySet对象的是(里面是字典或元组): values()? ? ? ?返回一个可 迭代的字典序列 values_list() 返回一个可迭代的元祖序列 返回的是具体的对象的(外面不再有QuerySet) get() first() last() 返回布尔值的是: exists() 返回的是数字的方法: count() 四。Django中的查询优化。 在django中,所有的查询都是惰性查询。也就是说,只有在真正需要数据的时候才会执行数据库语句。 这样的设计在于减轻数据库的压力。如,以下代码不会真正的执行sql语句: res = models.Book.objects.all() 只有print或者真正需要这个数据时才会访问数据库。 当我们需要查询一个书籍中的数目时有两种方法。 1.将数据通过value()筛选,得出特殊set对象: res = models.Book.objects.values(‘title‘) print(res) 这种操作数据库是一次性的,这样的结果是不能通过点操作进行的,其原理是搜索所有的title,生成字典添加到返回对象中 ? ? 2.通过all方法取出全部对象,通过点方法取出title,返回qureyset对象。 res = models.Book.objects.all() for i in res: 这种操作也是一次性的,一次将所有对象全部获取,放入列表中。 ? ? 但是取出的数据太过庞大,如何将这个操作进行优化呢? (1).only。 only的使用和value差不多,但是only获取的不是字典形式的数据,而是一个对象。它会将它所搜索的字段生成一个对象放入返回队列中。 res = models.Book.objects.only(‘title‘) for i in res: print(i.title) 可以看到它只对数据库进行了一次操作,之后的点操作都不再访问数据库: ? ? 但是当它点表中的其他数据是,它没有报错,却会一条条的访问数据库。: res = models.Book.objects.only(‘title‘) for i in res: print(i.price) 而且是在访问过所有数据之后又分别访问了一次: ? ? (2)defer defer提取出来的也是一个对象,和only是相反的操作,它会将该字段以外的对象一次性的提取出来,生成对象返回: res = models.Book.objects.defer(‘title‘) print(res) 它的sql语句(此处先不使用str方法): ? ? 当它点其他字段时,不会访问数据库,而点该字段时,会频繁访问数据库。 ? ? 场景二。外键查询优化。 当需要查询一个外键的时候,首先需要获取该表对象,然后再获取外键中的某些字段: res = models.Book.objects.all() for i in res: print(i.publish.name) 可以看到,每查询一次数据就会访问一次数据库,访问的是外键的那个数据库。 ? ? 为了减少对数据库的操作次数,可以使用两种查询方法(): (1)select_related res =models.Book.objects.select_related(‘publish‘) for i in res: print(i.publish.name) 它的原生sql语句就是把它外键的表进行连接,然后查询所有需要的字段: ? ? 随后再进行点操作就不需要走数据库了。 注意:select_related括号中只能放外键字段,而且只能是一对一或一对多的字段,但是可以持续的__进行拼接如:(外键字段1__外键字段2__外键字段3__外键字段4).它会把四张表全部拼接起来。 (2)prefetch_related prefetch_related这个操作会执行多次操作,先将这个表关联的字段的主键查询到手,再使用主键去找第二张表,最后将两张表全部返回。 res = models.Book.objects.prefetch_related(‘publish‘) for i in res: print(i.publish.name) ? ? 可以看到查询了两次数据库。 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。prefetch_related()的优化方式是分别查询每个表,然后用Python处理他们之间的关系。支持连多个外键。 总结: only()将括号内的字段数据生成一个对象列表返回。访问其他数据会再次寻找数据库 defer()除了括号中的字段,其他数据生成一个对象列表返回。访问该数据会再次寻找数据库。 select_related()。括号中只能放外键,且只支持1对1,1对多的外键,而且支持多__外键,将所有外键对应的表连接起来,返回对象列表。 prefetch_related()。括号中只能放外键,且只支持1对多,多对多的外键,支持多外键一起,将这个外键的id获取后,再去下一张表中寻找数据,获取外键。最后的拼接又python操作。 五。orm实现事务。 事务的四大特性 1.原子性。 2.一致性。 3.隔离性。 4.持久性。 操作事务需要导入模块: from django.db import transaction with transaction.atomic(): """数据库操作 在该代码块中书写的操作 同属于一个事务 """ models.Book.objects.create() models.Publish.objects.create() # 添加书籍和出版社 就是同一个事务 要么一起成功要么一起失败 print(‘出了 代码块 事务就结束‘) 其原生sql语句是: ? ? 可以看到没有出现事务相关的代码,其逻辑应该是再python中操作。 ? ? ? ? ? ? 补充: 除了昨天在设置中添加,还可以查询sql语句的方法是: 通过对象点query即可查询。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |