zoukankan      html  css  js  c++  java
  • 11.29

    1、非外键字段数据

    1.1 增加

    1、create方法

    #以books表为例
    #在create方法中,以逗号分隔,以关键字参数传字段数据,它们是AND关系
    book_obj = models.Books.objects.create()
    

    2、对象的绑定方法save

    '''
    1、先实例化一个表数据对象
    2、调用对象绑定方法save
    '''
    book_obj = models.Books()  # 实例化参数:关键字形式,字段名=字段值
    book_obj.save()
    

    1.2 查询

    1.2.1 常用方法

    (1)先获取QuerySet对象

    QuerySet对象

    filter查询出来的结果是一个QuerySet对象

    • 只要是QuerySet对象就可以无限制的调用QuerySet的方法

      res= models.Books.objects.filter(pk=1).filter().filter().filter().filter()

    • 只要是QuerySet对象就可以点query查看当前结果内部对应的sql语句

    1、all()

    查询所有,返回的结果为QuerySet对象

    res = models.Books.objects.all()
    

    2、filter()

    筛选,返回结果为QuerySet对象

    res = models.Books.objects.filter(pk=1,title='三')  # 支持多个参数 并且是and关系
    

    3、get()

    筛选,返回结果为数据对象

    条件不存在直接报错 并且查询条件必须是唯一的

     res = models.Books.objects.get(title='西游记')
    

    4、values()

    获取数据对象中指定的字段的值

    返回的结果为:queryset对象,值为列表套字典,如:

    res = models.Books.objects.values('title','price')
    print(res)
    '''
    <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>
    '''
    

    5、values_list()

    获取数据对象中指定的字段的值

    返回的结果为:queryset对象,值为列表套原则,如:

    res = models.Books.objects.values_list('title','price')
    print(res)
    '''
    <QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
    '''
    

    6、order_by()

    按照指定的顺序排序

    #默认升序
    
    res = models.Books.objects.order_by('price')
    res1 = models.Books.objects.all().order_by('price')
    
    #降序:排序字段前加-号
    
    res1 = models.Books.objects.all().order_by('-price')
    

    7、reverse()

    颠倒顺序

    前提是跌倒的对象必须有顺序,即被排序过了的

    res = models.Books.objects.all()
    res1 = models.Books.objects.all().reverse()
    

    8、exclude()

    排除什么什么之外,返回的是QuerySet对象

    res = models.Books.objects.all().exclude(title='三国演义')
    

    9、distinct()

    对查询结果进行去重操作

    去重的前提:数据必须是完全相同的情况下才能够去重,包括主键

    res = models.Books.objects.values('title','price')
    res = models.Books.objects.values('title','price').distinct()
    

    (2)基于QuerySet获取数据对象

    4、first()

    取queryset中第一个数据对象

    res = models.Books.objects.filter(title='西游记').first()
    

    5、last()

    取queryset中第一个数据对象

    res = models.Books.objects.filter(title='西游记').last()
    

    (3)基于数据对象获取数据值

    数据对象可以通过对象.属性的方式获取值

    # 以Books表的一条数据对象为例
    
    value = book_obj.name
    

    (4)其他

    1、exists()

    判断查询结果是否有值,返回结果是一个布尔值

    res = models.Books.objects.filter(pk=1).exists()
    

    2、count()

    统计数据的个数

    num = models.Books.objects.count()
    

    1.2.2 双下划线查询
    语法:字段名__方法名

    使用:一般作为filter()的过滤条件

    下表中示例语句,省略models.Books.objects.

    方法 说明 示例
    __gt 大于 filter(price__gt=500
    __lt 小于 filter(price__lt=400)
    __gte 大于等于 filter(price__gte=500)
    __lte 小于等于 filter(price__lte=500)
    __in 在...中 filter(price__in=[222,444,500])
    __range 在某区间内,参数为[],包含两端 filter(price__range=(200,800))
    __year 是某年 filter(publish_date__year='2019')
    __month 是某月 filter(publish_date__month='1')

    1.2.3 模糊查询

    语法:字段名__方法名

    使用:一般作为filter()参数

    以下示例,省略models.Books.objects.

    方法 说明 示例
    __startswith 以某字符串结尾 filter(title__startswith='三')
    __endswith 以某字符串结束 filter(title__endswith='1')
    __contains 包含某字符串 filter(title__contains='游')
    __icontains 包含某字符串,但忽略大小写 filter(title__icontains='p')

    1.3 修改

    1、QuerySet方法

     models.Books.objects.filter(pk=1).update(price=444.66)
    

    2、对象的绑定方法

    # 先获取对象
    
    book_obj = models.Books.objects.get(pk=1)
    
    # 再调用对象的绑定方法
    
    book_obj.save()
    

    注意点:

    利用对象的修改 内部其实是重头到位将数据的所有字段都重新写一遍

    1.4 删除

    1、QuerySet方法

     models.Books.objects.filter(pk=1).delete()
    

    2、对象的绑定方法

    # 先获取对象
    
    book_obj = models.Books.objects.get(pk=1)
    
    # 再调用对象的绑定方法
    
    book_obj.delete()
    

    2、外键字段数据

    2.0 级联更新

    指的是:当一对一或多对一关系中,表中的外键字段指向的数据被删除/更新时,该表中的数据也会被删除/更新

    mysql数据库,1版本默认级联更新、级联删除,2版本需要手动指定外键字段的约束条件

    ON DELETE CASCADE 级联删除
    ON UPDATE CASCADE 级联更新
    

    2.1 一对一

    2.2 一对多

    2.2.1 增加

    1、create()

    同非外键字段的create方法,传主键值

    2、传虚拟字段

    # 先查询关联的数据对象
    
    publish_obj = models.Publish.objects.filter(pk=2).first()
    
    # 再将对象作为参数传给外键(定义中写到的外键,是一个虚拟字段)
    
    models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)  # Book表中只有publish_id字段,publish字段是一个虚拟字段,是定义表时创建的
    

    2.2.2 修改

    1、update()

    同非外键字段的update方法

    models.Book.objects.filter(pk=1).update(publish_id=2)
    

    2、传虚拟字段

    使用update方法,但是以虚拟字段传参,同2.2.1

    2.2.3 删除

    models.Publish.objects.filter(pk=1).delete() 
    

    2.2.4 注意点

    默认级联删除,级联更新

    2.3 多对多

    以表Book和Author为例

    1、先查有外键的表中的数据对象

    book_obj = models.Book.objects.filter(pk=2).first()
    

    2、数据对象点外键,可能直接获取外键关联的数据对象

    book_obj.authors
    
    # 获取到关联的数据对象,即现在已经从Book跨到Author了
    

    此时就能操作多对多的记录了

    2.3.1 增加:add()

    使用add方法,给多对多关系的第三张表,即关系表中添加对应的关系

    绑定id值
    book_obj.authors.add(1)  # 在第三张表里面给书籍绑定一个主键为1的作者
    
    book_obj.author.add(1,2)  # 由于时多对多,因此可以绑定多个
    
    传对象
    # 先查出来对应的对象
    
    author_obj = models.Author.objects.filter(pk=1).first()
    author_obj1 = models.Author.objects.filter(pk=2).first()
    
    # 再使用add传值,操作关系表
    
    book_obj.authors.add(author_obj,author_obj1)  # 可以绑定多个
    

    2.3.2 修改:set()

    使用set方法,修改多对多关系表中的数据

    使用方式,同增加add

    注意点:

    传参数时,要用可迭代对象的形式,如元组

    set((1,2))  # 传数字
    set((author_obj,author_obj1))  # 传对象
    

    2.3.3 删除:remove()

    使用delete方法,删除多对多关系表中的数据

    使用方式,同增加add

    注意点:

    传参数时,不需要使用迭代对象,跟add方法基本一致

    2.3.4 清空 :clear()

    删除某个数据在第三张表中的所有记录,不需要参数

    book_obj = models.Book.objects.filter(pk=2).first()
    book_obj.authors.clear()
    

    2.4 跨表查询

    2.4.1 正反向查询

    以A查B为例,A中定义了A和B的关系,有外键key

    正向查询:从A查B

    反向查询:从B查A

    关键语法:

    # 正向查询 :对象.外键
    
    # 反向查询 :对象.关联的表名小写 + _set
    
    # 当一对一关系时,反向查询不需要加_set
    

    2.4.2 基于对象的跨表查询

    # 正向查询 :对象.外键
    
    a_obj = models.A.objects.filter(tk=2).first()
    b_obj = a_obj.key # 对象.外键即可得到关联的对象
    
    b_obj_list = a_obj.key.all()  # 当关联的数据对象有多个时,要加all()才能得到,否则得到的是app01.A.None
    
    # 反向查询 :对象.关联的表名小写 + _set
    
    b_obj = models.B.objects.filter(tk=3).first()
    a_obj = b_obj.a_set
    
    a_obj_list = b_obj.a_set.all()  # 同样,当关联多个数据时,要加all(),否则得到的是app01.B.None
    

    2.4.3 基于双下滑线的跨表查询

    1、写外键字段就相当于已经跨到外键字段所关联的表

    2、你想要改表的哪个字段信息 你只需要加__获取即可

    3、models后面点的谁 就以谁为基表

    示例:

    1.查询书籍pk为2的出版社名称
        # 正向
    res = models.Book.objects.filter(pk=2).values('publish__name') 
        # 反向
    res = models.Publish.objects.filter(book__pk=2).values('name')
    
    2.查询书籍pk为2的作者姓名和邮箱
    res = models.Book.objects.filter(pk=2).values('authors__name','authors__email')
    res = models.Author.objects.filter(book__pk=2).values('name','email')
    
    3.查询作者是egon的家庭地址
    res = models.Author.objects.filter(name='egon').values('author_detail__addr')
    res = models.AuthorDetail.objects.filter(author__name='egon').values('addr')
    
    4.查询出版社是东方出版社出版过的书的名字
    res = models.Publish.objects.filter(name='东方出版社').values('book__title')
    res = models.Book.objects.filter(publish__name='东方出版社').values('title')
    
    5.查询书籍pk是2的作者的手机号
    res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone')
    res = models.Author.objects.filter(book__pk=2).values('author_detail__phone')
    

    3、聚合查询

    3.1 聚合函数

    Max/Min/Sum/Avg/Count

    需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg

    关键语法:aggregate(分组名=聚合函数(参数))

    查询结果:字典

    注意点:

    1、聚合函数必须在分组之后才能使用

    2、没有分组,即默认整体就是一组

    3、给聚合函数的调用取名,则可以使用改名引用查询结果

    4、取名时,结果中的key为分组名,不取名时,django会自动用参数字段名__聚合函数名作为key

    # 参数一般为字段名,如:
    
    models.Book.objects.aggregate(mr = Max('price'))
    

    示例:

    # test.py 在测试文件中测试,打印结果
    
    # 1.筛选出价格最高的书籍
    
    res = models.Book.objects.aggregate(mr = Max('price'))
    
    # 2.求书籍总价格
    
    res = models.Book.objects.aggregate(sm = Sum('price'))
    
    # 3.求书籍平均价格
    
    res = models.Book.objects.aggregate(av = Avg('price'))
    
    # 4.同时使用多个聚合函数
    
    res = models.Book.objects.aggregate(Max('price'),Min('price'),Sum('price'),Count('price'),Avg('price'))
    

    3.2 分组查询

    1、关键字:annotate

    2、关键语法:QuerSet对象.annotate(聚合函数)

    示例:

    1.统计每一本书的作者个数、书名和对应的作者人数
    res = models.Book.objects.annotate(author_num=Count('authors__id')).values('title','author_num')
    print(res)
    
    2.统计出每个出版社卖的最便宜的书的价格、出版社的名字和价格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)
    
    按照其他字段分组
    res = models.Publish.objects.values('想要分组的字段名').annotate(min_price=Min('book__price')).values('name','min_price')
    print(res)
    
    3.统计不止一个作者的图书
    res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title','author_num')
    print(res)
    
    4.查询各个作者出的书的总价格  作者名字  总价格
    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    print(res)
    

    3、F查询

    3.1 使用F查询

    F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值

    需要导入模块:from django.db.models import F

    示例:

    from django.db.models import F
    
    # 1. 查询库存数大于卖出数的书籍
    
    res = models.Book.objects.filter(kun_cun__gt = F('mai_cun')).values('title')  # 后面的条件是来自于数据库的其他字段值
    
    # 2. 将所有书的价格上涨100块
    
    models.Book.objects.all().update(price=F('price') + 100)
    
    3.2 利用F查询,修改char字段
    
    # 将所有书的名称后面全部加上 "爆款" 后缀
    
    # 操作字符串数据需要借助于Concat方法
    
    from django.db.models.functions import Concat
    from django.db.models import Value
    ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
    

    4、Q查询

    4.1 Q查询的基本使用方法

    filter() 等方法中逗号隔开的条件是与的关系

    如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

    操作符:

    &:代表AND

    |:代表OR

    ~:代表取反

    注意点:

    0、使用逗号分隔多个参数

    1、可以组合使用操作符以及括号来编写任意复杂的Q对象

    2、查询函数可以混合使用Q 对象和关键字参数

    3、所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起

    4、但是,如果出现Q 对象,它必须位于所有关键字参数的前**

    示例:

    from django.db.models import Q
    
    # 1.查询一下书籍名称是三国演义 或者 库存数是500的书籍
    
    res = models.Book.objects.filter(title='三国演义',kun_cun=500)  # and关系
    res = models.Book.objects.filter(Q(title='三国演义'),Q(kun_cun=500))  # Q包裹之后逗号还是and关系
    res = models.Book.objects.filter(Q(title='三国演义') | Q(kun_cun=500))  #  |就是or的关系
    res = models.Book.objects.filter(~Q(title='三国演义') | Q(kun_cun=500))  #   ~就是not关系
    print(res)
    

    4.2 Q查询的高级使用方法

    q = Q()
    q.connector = 'or'  # 默认是and  可以改成or
    q.children.append(('title','三国演义'))
    q.children.append(('kun_cun__gt',500))
    res = models.Book.objects.filter(~q)  # 取反
    print(res)
    

    5、orm字段及参数

    5.1 常用字段

    CharField     varchar
    IntegerField   int
    BigIntegerField   bigint
    EmailField    varchar(254)
    DateField
    DateTimeField
    '''
        参数说明:
        auto_now:每次修改数据的时候 都会自动将当前修改时间更新上去  实时更新
        auto_now_add:在创建数据的时候 会将当前时间自动记录 之后不会自动修改  除非你人为修改
        '''
    AutoField     auto_increment   
    
    BooleanField    布尔值  
    '''
        该字段在存储的时候 你只需要传布尔值True或False
        它会自动存成1/0
    '''
    
    TextField  专门用来存大段文本
    
    FileField  专门用来文件路径   '/etc/data/a.txt'   
    
    upload_to = '/etc/data'
    '''
        给该字段传值的时候 直接传文件对象
        会自动将文件对象保存到upload_to后面指定的文件路径中
        然后将路径保存到数据库
    '''
    
    DecimalField(Field)
    '''
        1、10进制小数
        2、参数:
        max_digits,小数总长度
        decimal_places,小数位长度
    '''
    

    5.2 自定义char字段

    class MyCharField(models.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
    

    5.3 特殊参数choices
    1、定义字段时,指定参数choices

    2、choices的值为元组套元组(事先定义好,一般在该表类中定义该字段之前定义)

    3、每一个元组存放两个元素,形成一种对应关系

    4、往数据库中存值时,该字段的值存为元组第一个元素即可

    5、通过方式对象.get_字段名_display()获取对应的元组第二个元素值,当没有对应关系时,返回的是它本身

    示例:

    # 定义一个User表
    
    class User(models.Model):
        username = models.CharField(max_length=64)
        gender_choices = ((1,'男'),(2,'女'),(3,'其他'))
        gender = models.IntegerField(choices=gender_choices)
        
    
    # 同步迁移到数据库
    
    python manage.py makemigrations
    python manage.py migrate
    
    # 在test.py配置测试环境
    
    # 录入数据
    
    models.User.objects.create(username='aaa', gender=1)
    models.User.objects.create(username='bbb', gender=2)
    models.User.objects.create(username='ccc', gender=3)
    models.User.objects.create(username='ddd', gender=4)
    
    # 验证choices
    
    for user_obj in models.User.objects.all():
        print(user_obj.gender,end=' ')
        print(user_obj.get_gender_display())
    '''
    1 男
    2 女
    3 其他
    4 4
    '''    
    

    6、orm中的事务操作

    6.1 什么是事务

    将多个sql语句操作编程原子性操作,要么同时成功,否则有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)

    6.2 django使用事务

    from django.db import transaction
    
    with transaction.atomic():
        # 在缩进的代码中书写数据库操作
        # 该缩进内的所有代码 都是一个事务
        pass
    

    7、orm查询优化

    即尽量减少对数据库的操作,减轻数据库的压力

    # 在缩进的代码中书写数据库操作
    # 该缩进内的所有代码 都是一个事务
    

    ​ pass
    7、orm查询优化
    即尽量减少对数据库的操作,减轻数据库的压力

    7.1 orm惰性查询

    orm内所有的sql查询语句,都是惰性操作,即当你需要使用查询结果时,才会真正去执行sql语句访问数据库,否则是不会执行查询的

    可使用代码验证:

    1、配置settings文件,使得当执行sql语句时,在终端打印sql命令

    2、验证

    # 只查询,不使用查询结果
    
    models.User.objects.all()
    
    # 将查询结果赋值给变量res
    
    res = models.User.object.all()
    
    # 分别执行,查看终端的打印结果
    

    7.2 only与defer

    only查询:指定查询某字段时,将全部结果一次性获取出来,以后再访问该字段数据时,直接从内存中拿即可,不需要再操作数据库

    defer查询:指的是一次性获取指定字段之外的所有字段数据,封装到对象中,以后再访问这些字段数据时,直接从内存中拿即可,不需要再操作数据库

    代码:

    # 同样,可以配置settings,在终端中打印被执行的sql命令
    
    # all()查询
    
    res = models.User.objects.all()  # 访问一次数据库,打印一条sql命令,获取所有的User表中的数据到内存
    
    # only查询
    
    res = models.User.objects.only(username)  # 访问一次数据库,打印一条sql命令,仅仅获取username的所有数据到内存
    for user_obj in res:
        print(user_obj.username)  # 直接从内存中获取,不访问数据库,不打印sql命令
        print(user_obj.gender)  # 每执行一次,就访问一次数据库,打印一次sql命令
        
    
    # defer 查询
    
    res = models.User.objects.defer(usernmae)  # 访问一次数据库,打印一条sql命令,获取除了username之外的所有数据到内存
    for user_obj in res:
        print(user_obj.username)  # 每执行一次,访问一次数据库,打印一条sql命令
        print(user_obj.gender)  # 直接从内存中获取,不访问数据库,不打印sql命令
    

    当表中有外键时,使用方法减轻数据库的压力

    select_related:指定外键,将本表与该外键关联的表拼成一张表(inner join),并获取所有数据到内存,不能指定多对多关系的外键

    prefetch_related:指定外键,先查询本表所有数据,再根据外键查询对应的数据表所有数据,相当于子查询,可以指定多个外键,即多个子查询

  • 相关阅读:
    VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题
    C++中的预处理命令 .
    C++ sizeof用法 .
    详解C/C++预处理器 .
    C 风格字符串,C++string类,MFC,CString类的区别。
    VC: GDI绘图基本步骤总结 .
    关于字符数组 和 字符串比较 C++
    they're hiring
    HTTP Proxy Server
    Polipo
  • 原文地址:https://www.cnblogs.com/maqiaobin/p/11972876.html
Copyright © 2011-2022 走看看