加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

day56_9_20orm中的关键字段,orm查询13方法整合,查询优化和事务

发布时间:2020-12-15 07:41:44 所属栏目:Java 来源:网络整理
导读:一。常用字段。 在orm中有一些字段是常用字段: 1.AutoField 这个字段是自增的,必须填入参数primary_key=True,也就是说这个字段是表的主键,如果表类中没有自增列,就会自动创建名为id的自增列。 2.IntegerField 是一个整数类型,范围在?-2147483648到 2147

一。常用字段。

  在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字段对应关系
字段与sql语句对应

  字段对应的参数

  字段中也需要一些参数设置。

  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:
print(i.title)

  这种操作也是一次性的,一次将所有对象全部获取,放入列表中。

?

?  但是取出的数据太过庞大,如何将这个操作进行优化呢?

  (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即可查询。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读