ORM多表更新删除 查询

删除和修改

一对一和一对多的操作

# 修改和删除操作
def edit_book(request):
    # 一对一修改
    # 方式一: 通过模型类对象
    au_det_obj = models.AuthorDetail.objects.get(id=3)
    models.Author.objects.filter(id=1).update(name="bob",ad=au_det_obj)
    # # 方式二
    models.Author.objects.filter(id=5).update(name="jack",ad_id=1)

    # 一对多修改:同一对一
    # 方式一:
    pub_obj = models.Publish.objects.get(id=2)
    models.Book.objects.filter(id=6).update(pud=pub_obj)
    # 方式二:
    models.Book.objects.filter(id=7).update(pud_id=3)

    # 删除: 注意级联删除关系, 相关的数据都会删掉
    models.Author.objects.get(id=1).delete()
    models.Author.objects.filter(id=3).delete()
    models.AuthorDetail.objects.filter(id=4).delete()
    return HttpResponse('OK')

 

多对多关系的删除和更新

# 多对多的删除和更新
    # 删除remove
    book_obj = models.Book.objects.get(id=1)
    book_obj.authors.remove(8) # 删除一条
    book_obj = models.Book.objects.get(id=6)
    book_obj.authors.remove(7, 8) # 删除多条

    # 清空clear
    book_obj = models.Book.objects.get(id=4)
    book_obj.authors.clear()

    # 更新
    book_obj = models.Book.objects.get(id=3)
    book_obj.authors.set("7") # 参数是可迭代类型数据
    # 更改多条
    book_obj.authors.set([7,8,9])
    # set动作有两步:1 先执行clear   2 再执行add添加

 

多表查询

基于对象的跨表查询(子查询)

正向查询: 关系属性写在哪个表里面,那么通过这个表的数据,去查询关联的另外一张表的数据,就叫做正向查询,反之就是反向查询

# 一对一正向查询
    # 查陈六六作者的电话号码
    author_obj = models.Author.objects.get(name="陈六六")
    # author_obj.ad 找到了author_obj关联的作者详细信息表里面对应记录
    print(author_obj.ad.telephore) # 777
    # 反向查询 : 反向查询用关联它的模型类的名称小写
    # 查询地址为北京的作者名称
    aut_det_obj = models.AuthorDetail.objects.get(address="四川")
    print(aut_det_obj.author.name) # 陈七七

    # 一对多正向查询 同一对一查询
    # 查询人生是哪个出版社的
    book_obj = models.Book.objects.get(title="人生")
    print(book_obj.pud.name) # 小树出版社
    # 反向查询 模型类名小写_set
    # 查询小树出版社出版哪些书
    pub_obj = models.Publish.objects.get(name="小树出版社")
    print(pub_obj.book_set.all()) # <QuerySet [<Book: Book object>, <Book: Book object>]> 类似于objects控制器
    print(pub_obj.book_set.all().values("title")) # <QuerySet [{'title': '人生'}, {'title': '人类'}]>

    # 多对多查询
    # 正向查询 使用属性来查
    # 查询人生是谁写的
    book_obj = models.Book.objects.get(title="人生")
    print(book_obj.authors.all().values("name"))
    # <QuerySet [{'name': '陈六六'}, {'name': '陈七七'}, {'name': '张三'}]>
    # 反向查询 使用模型类名小写_set
    # 查询陈六六写了哪些书
    author_obj = models.Author.objects.get(name="陈六六")
    print(author_obj.book_set.all().values("title"))
    # <QuerySet [{'title': '人间'}, {'title': '人生'}]>
    return HttpResponse('OK')

 

查看原生SQL语句的方法

1 ORM语句.query
2 在settings配置文件中写上如下内容,就能够自动打印出我们执行orm语句对应的sql语句 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }  3 通过django配置的连接mysql的管道来查看(pymysql) from app01 import models def add_book(request): ''' 添加表记录 :param request: http请求信息 :return: ''' book_obj = models.Book(title='python',price=123,pub_date='2012-12-12',publish='人民出版社') book_obj.save() from django.db import connection #通过这种方式也能查看执行的sql语句 print(connection.queries) return HttpResponse('ok')

 

基于双下滑线的跨表查询(连表操作)

# 一对一正向查询  使用属性
    # 查询陈七七作者的地址
    res = models.Author.objects.filter(name="陈七七").values("ad__address")
    print(res) # <QuerySet [{'ad__address': '四川'}]>
    # 反向查询 表名小写
    res = models.AuthorDetail.objects.filter(author__name="陈七七").values("address")
    print(res) # <QuerySet [{'address': '四川'}]>

    # 一对多正向查询
    # 查询人世是哪个出版社的
    res = models.Book.objects.filter(title="人世").values("pud__name")
    print(res) # <QuerySet [{'pud__name': '小草出版社'}]>
    # 反向操作
    res = models.Publish.objects.filter(book__title="人世").values("name")
    print(res) # <QuerySet [{'name': '小草出版社'}]>

    # 多对多正向查询 使用关联属性
    # 查询人类这本书是谁写的
    res = models.Book.objects.filter(title="人类").values("authors__name")
    print(res) # <QuerySet [{'authors__name': 'jack'}]>
    # 反向查询
    res = models.Author.objects.filter(book__title="人类").values("name")
    print(res) # <QuerySet [{'name': 'jack'}]>

 

聚合查询(aggregate)

# 聚合查询
    from django.db.models import Max, Min, Avg, Count, Sum
    # 统计一下所有书籍的平均价格
    res = models.Book.objects.aggregate(Avg("price"))
    print(res) # {'price__avg': 62.757143}  结果是普通字典类型
    # 可以起别名
    res = models.Book.objects.aggregate(a=Avg("price"),b=Max("price"))
    print(res) # {'a': 62.757143, 'b': Decimal('99.90')}
    # aggregate方法可以看为是orm语句的结束语句,结果为普通字典类型,不能在继续调用queryset或者模型类对象提供的方法了

 

分组查询(annotate)

# 分组查询 必须制定别名
    # 查询一下每个出版社出版书的平均价格
    from django.db.models import Max, Min, Avg, Count, Sum
    res = models.Book.objects.values("pud_id").annotate(a=Avg("price"))
    print(res)
    # <QuerySet [{'pud_id': 1, 'a': 99.9}, {'pud_id': 2, 'a': 39.9}, {'pud_id': 3, 'a': 59.9}]>
    res = models.Book.objects.values("pud_id","id").annotate(a=Avg("price"))
    print(res) # values里面可以加多个分组条件
    # 以出版社名称分组的书的平均价格
    res = models.Book.objects.values("pud__name").annotate(a=Avg("price"))
    print(res)
    # <QuerySet [{'pud__name': '小草出版社', 'a': 39.9}, {'pud__name': '小树出版社', 'a': 59.9}, {'pud__name': '小花出版社', 'a': 99.9}]>

    res = models.Publish.objects.annotate(a=Avg("book__price"))
    print(res)
    # <QuerySet [<Publish: Publish object>, <Publish: Publish object>, <Publish: Publish object>]>
    # 返回结果是Publish的模型类对象,这个模型类对象里面包含Publish的所有属性数据,还有annotate的统计结果数据
    ret = res.values("name","a")
    print(ret)
    # <QuerySet [{'name': '小草出版社', 'a': 39.9}, {'name': '小树出版社', 'a': 59.9}, {'name': '小花出版社', 'a': 99.9}]>

 

F查询: 主要是针对本表的多个字段进行比较时使用

# F查询
    # F查询可以用来做本表不同字段之间的一个比较
    # 查询点赞数大于评论数的书籍
    from django.db.models import F
    res = models.Book.objects.filter(dianzan__gt=F("comment"))
    print(res)
    # <QuerySet [<Book: 人间>, <Book: 人生>, <Book: 人类>]>
    # F可以用来对本表数据进行一些统一操作(四则运算都支持)
    # 将所有的书籍上调10块钱
    models.Book.objects.all().update(price=F("price")+10)

 

Q查询: 可以进行多条件查询,查询关系可以是 或与非

# Q查询  filter中的查询条件默认是and关系
    # 可以进行多条件查询,查询关系可以是 或与非
    from django.db.models import Q
    # ~ 条件取反 ,&--and关系 ,|--or关系
    # 查询书名中包含以小开头的,或者评论数在350以上的
    res = models.Book.objects.filter(Q(title__startswith="")|Q(comment__gt=350))
    print(res)
    # <QuerySet [<Book: 小猫>, <Book: 猫生>, <Book: 小狗>]>

    # 查询书名中包含小的,或者评论数在350以上的,并且点赞数大于400的
    res = models.Book.objects.filter(Q(title__startswith="")|Q(comment__gt=350),dianzan__gt=400)
    print(res) # <QuerySet [<Book: 猫生>, <Book: 小狗>]>
    # 注意,如果结合逗号来进行and的关系查询,那么必须将没有Q包裹的查询条件放在Q包裹的查询条件后面

    #下面这种方式也可以,Q查询可以多层嵌套使用
    res = models.Book.objects.filter(Q(title__startswith="") | Q(comment__gt=350)&Q( dianzan__gt=400))
    print(res) # <QuerySet [<Book: 小猫>, <Book: 猫生>, <Book: 小狗>]>

 

posted on 2020-07-21 17:05  fdsimin  阅读(265)  评论(0编辑  收藏  举报