9,Django-13条基础-单表查询-外键-多对多-聚合和分组查询-F-Q-事物

/ORM操做13条基础-单表查询-外键-多对多-聚合和分组查询-F-Q-事物html

 

day74
1. 内容回顾
    1. ORM 
        1. 13条
            1. 返回queryset的
                all()
                filter()
                exclude()
                order_by()
                reverse()
                distinct()
                values()
                values_list()
            2. 返回对象的
                get()
                first()
                last()
            3. 返回布尔值
                exists()
            4. 返回数字
                count()
        2. django使用mysql数据库的步骤
            1. 建立一个mysql数据库
            2. 配置
                DATABASES = {
                    'default': {
                        'ENGINE': 'django.db.backends.mysql',
                        'NAME': 'orm_homework',
                        'USER': 'root',
                        'PASSWORD': '',
                        'HOST': '127.0.0.1',
                        'PORT': 3306,
                    }
                }
            3. 告诉django使用pymysql链接你的mysql数据库(mysqldb)
                在与settings同级目录下的__init__.py中写
                import pymysql
                pymysql.install_as_MySQLdb()
            4. 在APP下的models.py中写类(继承Model)
                
            5. 执行数据库迁移的命令
                python manage.py makemigrations # 记录models的变动记录
                python manage.py migrate        # 将变动记录同步到数据库中
            
        
        2. 周末做业
            见代码
        3. OneToOneField(to='关联的表')  (一对一)
            在ForeignKey基础上加一个约束  unique=true

            1. 全部的内容能够写在一个表中
            2. 有的字段不常查,但有的字段查的很频繁
        4. 外键ForeignKey
            book_obj.publisher       ——》 关联的出版社对象
            book_obj.publisher_id   
            
            反向查询:
                不指定related_name
                pub_obj.book_set    ——》关系管理对象
                指定related_name='books'
                pub_obj.books    ——》关系管理对象
        5. 多对多ManyToManyField
            book_obj.author
            多对多的方法:
                create()
                add()
                remove()
                set()
                clear()
        6. 单表的增删改查
            create
            delete
            update()
            .属性 = ''
            save()
        7. 进阶
            1. 聚合和分组
                aggregate   终止子句
                annotate   
            2. F 和 Q
            
                ~取反
                & and
                |3. 事务 
                
2. 今日内容
    0. 登陆的实例
    
    
    1. cookie
        1. cookie是什么?
            cookie是保存在浏览器上一组组键值对
            
        2. 特性:
            1. 是服务器让浏览器设置的。浏览器有权利不设置。
            2. 访问其余页面的时候携带着cookie。
        
        2. 能干什么?
            1. 作登陆
    
    
    
    2. session
        1. 保存在服务器上的键值对
        2. 一个cookie对应一个session
        流程:
            1. 给首次登陆的用户设置一个cookie  session:asdasdasasdasdas
            2. 开辟一块空间存session
            3. session中存要存的数据(键值对)
            4. 返回给浏览器cookie
            
        # 设置session
        request.session['is_login'] = 'True'
        # 获取session
        request.session.get('is_login', '')
            
            
            
        
            
        
            
                
                
                
                
笔记

 

 

https://www.cnblogs.com/maple-shaw/articles/9403501.htmlpython

https://www.cnblogs.com/maple-shaw/articles/9323320.htmlmysql

https://www.cnblogs.com/maple-shaw/articles/9414626.html -练习题git

# 查找全部书名里包含金老板的书
    # ret=models.Book.objects.filter(title__icontains='金老板').values_list('title')
    # print(ret)

    # 查找出版日期是2018年的书
    # ret=models.Book.objects.filter(publisher_date__year=2018).values_list('title','publisher_date')
    # print(ret)

    # 查找出版日期是2017年的书名
    # ret=models.Book.objects.filter(publisher_date__year=2017).values_list('title','publisher_date')
    # print(ret)


    # 查找价格大于10元的书
    # ret=models.Book.objects.filter(price__gt=10).values_list('title')
    # print(ret)

    # 查找价格大于10元的书名和价格
    # ret = models.Book.objects.filter(price__gt=10).values_list('title', 'price')
    # print(ret)

    # 查找memo字段是空的书
    # ret=models.Book.objects.filter(memo__isnull=True)
    # print(ret)


    # 查找在北京的出版社
    # ret=models.Publisher.objects.filter(city__icontains='北京').values_list('name','city')
    # print(ret)


    # 查找名字以沙河开头的出版社
    # ret = models.Publisher.objects.filter(name__startswith='沙河').values_list('name', 'city')
    # print(ret)





    ############----------------重点-------------------------####################

    # 查找“沙河出版社”出版的全部书籍
    # ret=models.Book.objects.filter(publisher__name='沙河出版社').values_list('publisher__name','title')
    # print(ret)


    # 查找每一个出版社出版价格最高的书籍价格
    # ret=models.Publisher.objects.annotate(max=Max('books__price')).values_list('name','books__title','max')
    # print(ret)

    # ret=models.Book.objects.filter(publisher__name='沙河出版社')
    # print(ret)

    # ret=models.Publisher.objects.filter(books__title='跟金老板学开车')
    # print(ret)

    # 查找每一个出版社的名字以及出的书籍数量
    # ret=models.Publisher.objects.annotate(num=Count('books')).values_list('name','num')
    # print(ret)


    # 查找做者名字里面带“小”字的做者
    # ret=models.Author.objects.filter(name__contains='小').values_list('name')
    # print(ret)
    # ret=models.Author.objects.all().values_list('name')
    # print(ret)

    # 查找年龄大于30岁的做者
    # ret=models.Author.objects.filter(age__gt=30).values_list('name','age','authors__title')
    # print(ret)

    # 查找手机号是155开头的做者
    # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','phone')
    # print(ret)
    # ret=models.Author.objects.all().values_list('phone')
    # print(ret)

    # 查找手机号是155开头的做者的姓名和年龄
    # ret=models.Author.objects.filter(phone__startswith=155).values_list('name','age')
    # print(ret)


    # 查找每一个做者写的价格最高的书籍价格
    # ret=models.Author.objects.annotate(max=Max('authors__price')).values_list('name','authors__price')
    # print(ret)

    # 查找每一个做者的姓名以及出的书籍数量
    # ret=models.Author.objects.all().annotate(num=Count('authors')).values_list('name','num')
    # print(ret)




    # 查找书名是“跟金老板学开车”的书的出版社
    # book_obj=models.Book.objects.filter(title='跟金老板学开车')
    # ret=book_obj.publisher
    # print(ret)


    # 查找书名是“跟金老板学开车”的书的出版社所在的城市

    # book_obj=models.Book.objects.get(title='跟金老板学开车')
    # ret=book_obj.publisher.city
    # print(ret)

    # 查找书名是“跟金老板学开车”的书的出版社的名称
    # book_obj=models.Book.objects.filter(title='跟金老板学开车')
    # ret=book_obj.publisher.name
    # print(ret)

    # 查找书名是“跟金老板学开车”的书的出版社出版的其余书籍的名字和价格
    # book_obj=models.Book.objects.get(title='跟金老板学开车')
    # ret=book_obj.publisher.books.exclude(title='跟金老板学开车').values_list('title','price')
    # print(ret)

    # ret=models.Publisher.objects.get(books__title='跟金老板学开车').books.exclude(title='跟金老板学开车').values_list('title','price')
    # print(ret)

    # obj=models.Publisher.objects.get(book__title='跟金老板学开车').book_set.exclude(title='跟金老板学开车').values_list('title','price')
    # ret=obj.book_set.all()
    # print(obj)

    # 查找书名是“跟金老板学开车”的书的全部做者

    # ret=models.Book.objects.get(title='跟金老板学开车').author.all()
    # print(ret)

    # 查找书名是“跟金老板学开车”的书的做者的年龄
    # ret=models.Book.objects.get(title='跟金老板学开车').author.all().values_list('age','name')
    # print(ret)


    # 查找书名是“跟金老板学开车”的书的做者的手机号码
    # ret=models.Book.objects.get(title='跟金老板学开车').author.all().values_list('phone','name')
    # print(ret)

    # 查找书名是“跟金老板学开车”的书的做者们的姓名以及出版的全部书籍名称和价钱
    # book_obj = models.Book.objects.get(title='跟金老板学开车')
    # ret=book_obj.author.all()
    # for aut in ret:
    #     print(aut)
    #     ret=aut.authors.all().values_list('title','price')
    #     print(ret)

    # ret=models.Author.objects.filter(authors__title='跟金老板学开车').values('name','authors__title','authors__price')
    # print(ret)
练习题答案-本身作的

 

sql

 

/数据库

 

/django

 

/浏览器

 

QuerySet API reference

https://docs.djangoproject.com/en/1.11/ref/models/querysets/服务器

 

/cookie

 

/

 

/

 

 

 /

先创建项目,各项配置,链接数据库,操做的是出版社,书籍,做者,存在外键,多对多关系

 

在Python脚本中调用Django环境

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
#上面的代码,在manage.py文件里也有,能够考虑复制过来

   #引入django import django django.setup()   
  #引入models
from app01 import models books = models.Book.objects.all() print(books)

 

注意:

1,在项目下建一个文件夹,而后建一个py文件,把上面代码粘贴进去,

2,写好语句后, 右键执行便可,不用在启动django项目,直接看结果,

 

示例代码:

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")


    import django
    django.setup()

    from app01 import models
    ret = models.Person.objects.all()
    print(ret[0],'**',type(ret),'**',type(ret[0]))

输出结果

ret=models.Person.objects.all()
#类型是类,QuerySet对象
type(ret)---><class 'django.db.models.query.QuerySet'>
    
ret[0]
Person object    

type(ret[0])
<class 'app01.models.Person'>

 /

 

 

 /

order_by的默认排序, ordering=('id','age'),ID同样,再按age进行排序,

class Person(models.Model):
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=32)
    age=models.IntegerField()
    birth=models.DateField()

    def __str__(self):
        return "<Person obj:{} {}>".format(self.id,self.name)
    
    # 加上这个以后,默认取出来就是已经排序的
    class Meta:
        #后面要写元组,
        ordering=('id')
默认取出来已经排序了,

下面再写的取出来就是倒序了

ret=models.Person.objects.all().reverse()

也能够这样写,

models.Person.objects.all().order_by('id').reverse()

 

具体演示代码

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django
    django.setup()

    from app01 import models


    # all  获取全部对象   ——》 QuerySet
    ret = models.Person.objects.all()

    # get  获取单独的对象  ——》 对象
    # 找不到或者找到多个就报错
    ret= models.Person.objects.get(id=1,name='阿旭')

    # filter 过滤 获取全部知足条件的对象   ——》QuerySet
    ret = models.Person.objects.filter(id=1)

    # exclude  获取不知足条件的全部对象
    ret = models.Person.objects.exclude(id=1)

    # values   ——》QuerySet  元素是字典
    # 不写参数   默认全部字段的名字和值
    # 写参数     拿到指定字段的名字和值
    ret = models.Person.objects.all().values('id','name')
    ret = models.Person.objects.values('id','name')
    # values_list   ——》QuerySet  元素是元组  只有值没有字段名
    # 不写参数   默认全部字段值
    # 写参数     拿到指定字段值
    ret = models.Person.objects.values_list('name','id')
    # print(ret)

    # for i in ret :
    #     print(i,type(i))
    #  reverse 对已经排序的QuerySet进行反转
    ret = models.Person.objects.all().reverse()


    # distinct 去重  ——》QuerySet


    # count 对QuerySet中的元素进行计数
    ret = models.Person.objects.filter(id=100).count()


    # first  取QuerySet中的第一个元素
    ret = models.Person.objects.all().first()

    # last  取QuerySet中的最后一个元素
    ret = models.Person.objects.all().last()
    ret = models.Person.objects.values_list().last()

    ret = models.Person.objects.filter(id=100).first()

    # exists 判断查询结果是否有值
    ret = models.Person.objects.filter(id=100).exists()
    # print(ret)

    # order_by 按字段进行排序 ——》QuerySet
    ret =models.Person.objects.order_by('age')
    print(ret)
具体演示代码+注释

 /

 

/

返回QuerySet对象的方法有:

all(),

filter(),

exclude(),

order_by(), 里面能够放多个参数

reverse(),对已经排序的进行翻转

distinct(),去重

 

特殊的QuerySet

values()       返回一个可迭代的字典序列,里面能够放参数,放了参数就是仅显示参数的内容,

values_list() 返回一个可迭代的元祖序列, 也能够放参数,

 

返回具体对象的

get(), 取不到或者取到多个会报错

first(), 取不到是Null

last().

 

返回布尔值的方法有:

exists()

返回数字的方法有:

count()

 

单表查询的下划线

id__lt,id__gt,id__in,id__range=[]是列表
name__contains='str'
name__icontains='str'
name__startswith='xx'
name__endswith='xx'
name__iendswith='xx'
birth__year

 


eq 就是 EQUAL等于 ne 就是 NOT EQUAL不等于 gt 就是 GREATER THAN大于  lt 就是 LESS THAN小于 gte 就是 GREATER THAN OR EQUAL 大于等于 lte 就是 LESS THAN OR EQUAL 小于等于

 

 

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")


    import django
    django.setup()

    from app01 import models
    ret = models.Person.objects.all()

    #小于10的,less than
    ret=models.Person.objects.filter(id__lt=10)

    #大于1的,great than
    ret=models.Person.objects.filter(id__gt=3)
    #大于等于3的,
    ret=models.Person.objects.filter(id__gt=3)
    #大于3小于5的,
    ret=models.Person.objects.filter(id__gt=3,id__lt=5)
    #取反,拿出小于等于3的,
    ret=models.Person.objects.exclude(id__gt=3)
    #还能够设置范围,还能够换成exclude
    ret=models.Person.objects.filter(id__in=[1,3,5])
    #使用range,1和5都能取到,
    ret=models.Person.objects.filter(id__range=[1,5])
    #查选包含特定字符的,
    ret=models.Person.objects.filter(name__contains='')
    #注意加了一个i,是不区分大小写的意思,
    ret=models.Person.objects.filter(name__icontains='')

    #表示以哪一个字符为开头
    ret=models.Person.objects.filter(name__startswith='')
    #以什么结尾,
    ret=models.Person.objects.filter(name__endswith='')
    #加了一个i,不区分大小写,
    ret=models.Person.objects.filter(name__iendswith='')
    
    #查找日期符合条件的,
    ret=models.Person.objects.filter(birth__year='2018')
    ret=models.Person.objects.filter(birth__month='09')
    ret=models.Person.objects.filter(birth__year='2018',birth__month='09')

    print(ret)
示例代码

 

 

ForeignKey

Django终端打印SQL语句

在Django项目的settings.py文件中在最后复制粘贴以下代码:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}
打印SQL语句

 

即为你的Django项目配置上一个名为django.db.backends的logger实例便可查看翻译后的SQL语句。

 

 

 

正向查询

/

 

/

外键设置在书籍,经过book查询publisher,称之为正向查询,反过来就是反向查询,

 

#book_obj.publishr是直接拿到了publisher对象了,关联的出版社对象,
print(book_obj.publisher,type(book_obj.publisher))

输出:Publisher object <class 'app01.models.Publisher'>

#区分两者的sql语句条数
print(book_obj.publisher_id)
print(book_obj.publisher.id)

 

对象查找(跨表)

语法:

对象.关联字段.字段

book_obj = models.Book.objects.first()  # 第一本书对象
print(book_obj.publisher)  # 获得这本书关联的出版社对象
print(book_obj.publisher.name)  # 获得出版社对象的名称

 

字段查找

models.Book.objects.filter(publisher__name='新华出版社')  #查出 出版社='新华出版社' 出版的全部书,

 

 

反向查找

此处就是publisher查找book

/

 

 

对象查找

语法:

obj.表名_set

 

拿到关联对象

publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象

books = publisher_obj.book_set.all() # 找到第一个出版社出版的全部书

titles = books.values_list("title") # 找到第一个出版社出版的全部书的书名

 

 

示例代码1

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_practice.settings")
    import django

    django.setup()

    from app01 import models
    # 正向查询   book ——》 publisher
    # 基于对象查询
    # book_obj = models.Book.objects.get(id=1)
    # print(book_obj.id)
    # print(book_obj.title)
    # print(book_obj.publisher_id)
    # print(book_obj.publisher_id)  # 关联的出版社对象
    # print(book_obj.publisher.id)  # 关联的出版社对象
    # print(book_obj.publisher.name)

    # 基于字段查询
    # ret= models.Book.objects.filter(publisher__name='沙河出版社')
    # ret= models.Book.objects.filter(publisher_id=1)
    # print(ret)


    # 反向查询   publisher ——》 book
    # 基于对象的查询
    # 一 —— 》 多    表名小写_set ——》 管理对象   .all()  出版社关联的全部书籍对象
    pub_obj = models.Publisher.objects.first()

    # 表名小写_set
    # print(pub_obj)
    # ret = pub_obj.book_set.all()
    # print(pub_obj.book_set,type(pub_obj.book_set))
    # print(ret)

    # 指定了related_name  books
    # print(pub_obj.books.all())

    # 基于字段的查询
    ret = models.Publisher.objects.filter(xx__title='跟太亮学开车')
    print(ret)
练习代码

 

关于查找时,能够简化的写法,

注意:

在models里面须要对应设置,注意related_name的添加,  也是反向查询用的,

class Book(models.Model):
    title=models.CharField(max_length=32)
    #下面一行是要关联的外键
    publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE)

 

 

 

 

字段查询

ret=models.Publisher.objects.filter(books__title='这就是书名')  #此处的books__title books是related_name
#若是下面图片的related_query_name='xx',写了,上面的books__title就要换成:xx__title,

与图片的关系

 

create

pub_obj=models.Publisher.objects.first()
pub_obj.books.create(title='跟老男孩学思想')

 /

 

 

 /

 

ManyToManyField,多对多的管理

class RelatedManager

"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。

它存在于下面两种状况:

  1. 外键关系的反向查询
  2. 多对多关联关系

简单来讲就是当 点后面的对象 可能存在多个的时候就可使用如下的方法。

 

拿到管理对象,

    author_obj=models.Author.objects.get(id=1)
    # books就是设置的那个多对多,books=models.ManyToManyField('Book')
    print(author_obj.books,type(author_obj.books))
    #拿到管理对象,
    # 输出:app01.Book.None <class 'django.db.models.fields.related_descriptors
    print(author_obj.books.all())
    #拿到QuerySet
    #输出:<QuerySet [<Book: <Person obj:5 跟太亮学开车>>, <Book: <Person obj:6 跟太白学烫头>>]>

 

方法

create

#create

    # 1,建立书籍对象(与出版社进行关联)
    # 2,该对象和做者
    author_obj = models.Author.objects.get(id=1)

  
  此处的books就是以前的->
books=models.ManyToManyField('Book')
    author_obj.books.create(title='XX与嫂子的故事',publisher_id=1)

 /

 

/

 

/

add:把指定的model对象添加到关联对象集中。

add()括号里面能够放一个或多个数据, 能够放id,还能够放对象,

#给做者添加书籍,
    author_obj = models.Author.objects.get(id=1)
    #能够添加一个或多个,add()
    # author_obj.books.add(9)
    author_obj.books.add(5,6,8,9)

区分与set的不一样
author_obj.books.set([1,6,8,9]) 

 

另外一种添加方式

   author_obj=models.Author.objects.get(id=1)
    # 获取指定id的书籍
    books=models.Book.objects.filter(id__in=[1,6,8,9])
    #须要打散才能进行传参
    author_obj.books.add(*books)

 

 

set:更新model对象的关联对象。

与add对比使用,add是添加的一个id,或者一个对象,

set能够添加列表,或者queryset集合,

    author_obj=models.Author.objects.get(id=1)
    books=models.Book.objects.filter(id__in=[1,6,8,9])

    # 下面两行的代码是等价的,
    # author_obj.books.set([1,6,8,9])
    author_obj.books.set(books)

 

 

/

 

/

remove():从关联对象集中移除执行的model对象,

author_obj=models.Author.objects.get(id=1)
books=models.Book.objects.filter(id__in=[1,6,8,9])
# remove
能够移除一个或多个
author_obj.books.remove(1)
author_obj.books.remove(6,8,9)

# 能够移除对象
author_obj.books.remove(*books)

 

clear()

从关联对象集中移除一切对象。

author_obj=models.Author.objects.get(id=1)

#把跟这个做者关联的书,都清空掉,
author_obj.books.clear()

 

 

对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。

设置null=True

就是删除出版社跟书的对应关系时,外键没有了,往数据库写的时候,写不进去,须要设置null=True才能写进去,

在models里设置Book类,而后执行两条命令.

 

注意:

  1. 对于全部类型的关联字段,add()、create()、remove()和clear(),set()都会立刻更新数据库。换句话说,在关联的任何一端,都不须要再调用save()方法。

设置null=True

publisher=models.ForeignKey('Publisher',related_name='books',on_delete=models.CASCADE,null=True)

 

设置null=True以后,示例代码

   pub_obj=models.Publisher.objects.get(id=1)

    #一对多的管理对象remove不能使用id,使用对象
    # pub_obj.books.remove(models.Book.objects.get(id=5))

    #清空这个出版社下全部关联的书,
    pub_obj.books.clear()

 /

 

/

 

聚合查询和分组查询

 

models里面,Book类添加包含小数的字段

price=models.DecimalField(max_digits=5,decimal_places=2)

 

聚合

1,aggregate的使用,观察输出结果,

ret=models.Book.objects.all().aggregate(Avg('price'))
print(ret,type(ret))
# 输出:{'price__avg': 50.0} <class 'dict'>

还能够更名字
ret=models.Book.objects.all().aggregate(make_name=Avg('price'))
print(ret,type(ret))
# {'make_name': 50.0} <class 'dict'>

还能够多放参数
ret=models.Book.objects.all().aggregate(Avg('price'),Max('price'))


 

2,能够更名字,还能够多放参数,

/

 

/

 

分组

1,统计每本书的做者个数

# 统计每本书的做者个数
    #.all能够省略不写,
    # ret=models.Book.objects.all().annotate(Count('author'))
    ret=models.Book.objects.annotate(Count('author'))
    for i in ret.values():
        print(i)

 

输出结果

'''输出:
        {'id': 1, 'title': '宫保鸡丁指南', 'publisher_id': 1, 'price': Decimal('10.00'), 'author__count': 1}
{'id': 2, 'title': '包子真贵', 'publisher_id': 4, 'price': Decimal('20.00'), 'author__count': 1}
{'id': 3, 'title': '陶馨园真便宜', 'publisher_id': 5, 'price': Decimal('30.00'), 'author__count': 1}
{'id': 4, 'title': '护国寺豆汁真骚', 'publisher_id': 3, 'price': Decimal('40.00'), 'author__count': 0}
{'id': 5, 'title': '跟太亮学开车', 'publisher_id': 1, 'price': Decimal('50.00'), 'author__count': 1}
{'id': 6, 'title': '跟太白学烫头', 'publisher_id': 1, 'price': Decimal('60.00'), 'author__count': 1}
{'id': 7, 'title': '新华字典', 'publisher_id': 2, 'price': Decimal('70.00'), 'author__count': 1}
{'id': 8, 'title': '戴绿与嫂子的故事', 'publisher_id': 1, 'price': Decimal('80.00'), 'author__count': 0}
{'id': 9, 'title': '跟老男孩学思想', 'publisher_id': 1, 'price': Decimal('90.00'), 'author__count': 0}
    '''
输出结果

 

2,统计每一个出版社最便宜的书,

ret=models.Publisher.objects.annotate(Min('books__price')).values()
    for i in ret.values():
        print(i)

 

3,统计不止一个做者的图书,

#统计不止一个做者的图书,
    ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
    print(ret)
 

4,查询做者出的书的总价格

# 查询做者出的书的总价格
    ret=models.Author.objects.annotate(sum=Sum('books__price')).values()
    print(ret)

 

 

F查询个Q查询

 

先进行导入

from django.db.models import F

 

示例代码

# F查询
    from django.db.models import F
    # ret=models.Book.objects.filter(sale__gt=50).values()
    #F查询,直接查出sale大于kucun的,
    ret=models.Book.objects.filter(sale__gt=F('kucun')).values()
    #还能够加减数值
    ret=models.Book.objects.filter(sale__gt=F('kucun')+30).values()
    print(ret)

 

对数据的修改:update与save的区别,save的效率要慢,

#对数据的修改,
    models.Book.objects.all().update(sale=100)

    #区分update与save的差异,

    book_obj=models.Book.objects.get(id=1)
    book_obj.sale=0
    book_obj.save()
    

 

Q查询

filter() 等方法中的关键字参数查询都是一块儿进行“AND” 的。

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

先进行导入

from django.db.models import Q

 

ret=models.Book.objects.filter(Q(id__lt=3)|Q(id__gt=5))
    # print(ret)
    for i in ret:
        print(i)

    ret = models.Book.objects.filter(Q(id__gt=3)&Q(id__lt=9))
    # print(ret)
    for i in ret:
        print(i)

 

还能够进行取反

ret=models.Book.objects.filter(~Q(id__lt=3)|Q(id__gt=5))
    # print(ret)
    for i in ret:
        print(i)

 

/

事物:要成功都成功,要失败都失败,

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    import datetime
    from app01 import models

    try:
        from django.db import transaction
        with transaction.atomic():
            new_publisher = models.Publisher.objects.create(name="火星出版社")
            models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社id
    except Exception as e:
        print(str(e))
View Code

 

 

 

Django ORM执行原生SQL

# extra
# 在QuerySet的基础上继续执行子语句
# extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

# select和select_params是一组,where和params是一组,tables用来设置from哪一个表
# Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
# Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
# Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
# Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

举个例子:
models.UserInfo.objects.extra(
                    select={'newid':'select count(1) from app01_usertype where id>%s'},
                    select_params=[1,],
                    where = ['age>%s'],
                    params=[18,],
                    order_by=['-age'],
                    tables=['app01_usertype']
                )
                """
                select 
                    app01_userinfo.id,
                    (select count(1) from app01_usertype where id>1) as newid
                from app01_userinfo,app01_usertype
                where 
                    app01_userinfo.age > 18
                order by 
                    app01_userinfo.age desc
                """


# 执行原生SQL
# 更高灵活度的方式执行原生SQL语句
# from django.db import connection, connections
# cursor = connection.cursor()  # cursor = connections['default'].cursor()
# cursor.execute("""SELECT * from auth_user where id = %s""", [1])
# row = cursor.fetchone()


ORM 执行原生SQL的方法
View Code

 

 

QuerySet方法大全

##################################################################
# PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
##################################################################

def all(self)
    # 获取全部的数据对象

def filter(self, *args, **kwargs)
    # 条件查询
    # 条件能够是:参数,字典,Q

def exclude(self, *args, **kwargs)
    # 条件查询
    # 条件能够是:参数,字典,Q

def select_related(self, *fields)
    性能相关:表之间进行join连表操做,一次性获取关联的数据。

    总结:
    1. select_related主要针一对一和多对一关系进行优化。
    2. select_related使用SQL的JOIN语句进行优化,经过减小SQL查询的次数来进行优化、提升性能。

def prefetch_related(self, *lookups)
    性能相关:多表连表操做时速度会慢,使用其执行屡次SQL查询在Python代码中实现连表操做。

    总结:
    1. 对于多对多字段(ManyToManyField)和一对多字段,可使用prefetch_related()来进行优化。
    2. prefetch_related()的优化方式是分别查询每一个表,而后用Python处理他们之间的关系。

def annotate(self, *args, **kwargs)
    # 用于实现聚合group by查询

    from django.db.models import Count, Avg, Max, Min, Sum

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
    # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
    # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1

    v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
    # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1

def distinct(self, *field_names)
    # 用于distinct去重
    models.UserInfo.objects.values('nid').distinct()
    # select distinct nid from userinfo

    注:只有在PostgreSQL中才能使用distinct进行去重

def order_by(self, *field_names)
    # 用于排序
    models.UserInfo.objects.all().order_by('-id','age')

def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    # 构造额外的查询条件或者映射,如:子查询

    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

 def reverse(self):
    # 倒序
    models.UserInfo.objects.all().order_by('-nid').reverse()
    # 注:若是存在order_by,reverse则是倒序,若是多个排序则一一倒序


 def defer(self, *fields):
    models.UserInfo.objects.defer('username','id')
    或
    models.UserInfo.objects.filter(...).defer('username','id')
    #映射中排除某列数据

 def only(self, *fields):
    #仅取某个表中的数据
     models.UserInfo.objects.only('username','id')
     或
     models.UserInfo.objects.filter(...).only('username','id')

 def using(self, alias):
     指定使用的数据库,参数为别名(setting中的设置)


##################################################
# PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
##################################################

def raw(self, raw_query, params=None, translations=None, using=None):
    # 执行原生SQL
    models.UserInfo.objects.raw('select * from userinfo')

    # 若是SQL是其余表时,必须将名字设置为当前UserInfo对象的主键列名
    models.UserInfo.objects.raw('select id as nid from 其余表')

    # 为原生SQL设置参数
    models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])

    # 将获取的到列名转换为指定列名
    name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
    Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)

    # 指定数据库
    models.UserInfo.objects.raw('select * from userinfo', using="default")

    ################### 原生SQL ###################
    from django.db import connection, connections
    cursor = connection.cursor()  # cursor = connections['default'].cursor()
    cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    row = cursor.fetchone() # fetchall()/fetchmany(..)


def values(self, *fields):
    # 获取每行数据为字典格式

def values_list(self, *fields, **kwargs):
    # 获取每行数据为元祖

def dates(self, field_name, kind, order='ASC'):
    # 根据时间进行某一部分进行去重查找并截取指定内容
    # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
    # order只能是:"ASC"  "DESC"
    # 并获取转换后的时间
        - year : 年-01-01
        - month: 年-月-01
        - day  : 年-月-日

    models.DatePlus.objects.dates('ctime','day','DESC')

def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
    # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
    # kind只能是 "year", "month", "day", "hour", "minute", "second"
    # order只能是:"ASC"  "DESC"
    # tzinfo时区对象
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
    models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))

    """
    pip3 install pytz
    import pytz
    pytz.all_timezones
    pytz.timezone(‘Asia/Shanghai’)
    """

def none(self):
    # 空QuerySet对象


####################################
# METHODS THAT DO DATABASE QUERIES #
####################################

def aggregate(self, *args, **kwargs):
   # 聚合函数,获取字典类型聚合结果
   from django.db.models import Count, Avg, Max, Min, Sum
   result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
   ===> {'k': 3, 'n': 4}

def count(self):
   # 获取个数

def get(self, *args, **kwargs):
   # 获取单个对象

def create(self, **kwargs):
   # 建立对象

def bulk_create(self, objs, batch_size=None):
    # 批量插入
    # batch_size表示一次插入的个数
    objs = [
        models.DDD(name='r11'),
        models.DDD(name='r22')
    ]
    models.DDD.objects.bulk_create(objs, 10)

def get_or_create(self, defaults=None, **kwargs):
    # 若是存在,则获取,不然,建立
    # defaults 指定建立时,其余字段的值
    obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})

def update_or_create(self, defaults=None, **kwargs):
    # 若是存在,则更新,不然,建立
    # defaults 指定建立时或更新时的其余字段
    obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})

def first(self):
   # 获取第一个

def last(self):
   # 获取最后一个

def in_bulk(self, id_list=None):
   # 根据主键ID进行查找
   id_list = [11,21,31]
   models.DDD.objects.in_bulk(id_list)

def delete(self):
   # 删除

def update(self, **kwargs):
    # 更新

def exists(self):
   # 是否有结果


QuerySet方法大全
View Code

 

#统计不止一个做者的图书,
ret=models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)
print(ret)

相关文章
相关标签/搜索