zoukankan      html  css  js  c++  java
  • Django ORM操作练习 以及 F和Q的使用方法 双下条件等等

    表关系:

    from django.db import models
    # Create your models here.
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
        # 与AuthorDetail建立一对一的关系
        authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)
    
    
    class AuthorDetail(models.Model):
        nid = models.AutoField(primary_key=True)
        birthday = models.DateField()
        telephone = models.BigIntegerField()
        addr = models.CharField(max_length=64)
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
    
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        publishDate = models.DateTimeField()
        price = models.DecimalField(max_digits=5, decimal_places=2)
    
        # 与Publish建立一对多的关系,外键字段建立在多的一方
        publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)
        # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
        authors = models.ManyToManyField(to='Author', )

    练习:

    一、基于对象查询(子查询)

      1、正向查询:出版社与书籍属于一对多关系,关系字段在书籍表中,通过书籍表找出版社属于正向查询

        # 查询书籍名称是python的出版社名称,对象点字段的形式查询即可(obj.publish.name)
        ret = models.Book.objects.filter(title='python').first().publish.name
        print(ret)

      2、反向查询: 出版社与书籍属于一对多关系,关系字段在书籍表中,通过出版社表找书籍表属于反向查询

    # 查询出版社id为1的出版社,出版过哪些书籍。表名加__set
        ret = models.Publish.objects.filter(nid=1).first().book_set.values('title')
        print(ret)

    二、基于QuerySet和"__"查询(连表查询)

      1、正向查询:出版社与书籍属于一对多关系,关系字段在书籍表中,通过书籍表找出版社属于正向查询

        # 查询python这本书籍的出版社的邮箱:values('关联字段__字段')
        ret = models.Book.objects.filter(title='python').values('publish__email')
        print(ret)
      ret = ret = models.Publish.objects.filter(book__title='python').values('email')
      print(ret)

      2、反向查询:同理,通过出版社表找书籍表属于反向查询

    # 查询永丰出版社出版过的书籍名称:values('表名__字段')
        # 方法一:
        ret = models.Publish.objects.filter(name='永丰出版社').values('book__title')
        print(ret)
    
        # 方法二 
        ret = models.Book.objects.filter(publish__name='永丰出版社').values('title')
        print(ret)

    三、聚合查询

      aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典,而不是QuerySet和一个具体的对象

    from django.db.models import Count, Avg, Sum, Max, Min
        # 查询所有书籍的价格总和
        ret = models.Book.objects.aggregate(Sum('price'))
        print(ret)

    四、分组查询:annotate前面是什么,就按照什么分组

        # 查询永丰出版社的所有书籍的平均价格
        ret = models.Publish.objects.values('name').annotate(avg=Avg('book__price')).values('name', 'avg').filter(name='永丰出版社')
        print(ret)

    ORM语句与SQL语句对照:

       gt大于、lt小于、order_by排序

        # 查询书籍平均价格低于100的出版社:filter('字段名__lt')
        ret = models.Publish.objects.values('name').annotate(avg=Avg('book__price')).values('name', 'avg').filter(avg__lt=100)
        print(ret)
        # 按照书籍平均价格对出版社进行排序
        ret = models.Publish.objects.values('name').annotate(avg=Avg('book__price')).values('name', 'avg').order_by('avg')
        print(ret)
     
    F和Q:
      F查询:

    在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

      Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

    示例1:

    查询评论数大于收藏数的书籍

    from django.db.models import F
    models.Book.objects.filter(commnet_num__gt=F('keep_num'))

    Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

    models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

    修改操作也可以使用F函数,比如将每一本书的价格提高30元

    models.Book.objects.all().update(price=F("price")+30)

    引申:

    如果要修改char字段咋办?

    如:把所有书名后面加上(第一版)

    >>> from django.db.models.functions import Concat
    >>> from django.db.models import Value
    >>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))

      Q查询:

    filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

    示例1:

    查询作者名是小仙女或小魔女的

    models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

    你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

    示例:查询作者名字是小仙女并且不是2018年出版的书的书名。

    >>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
    <QuerySet [('番茄物语',)]>

    查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

    例如:查询出版年份是2017或2018,书名中带物语的所有书。

    >>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
    <QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>, <Book: 橘子物语>]>
     
      Q的高级用法:
        q = Q()
        q.connector = 'or'  # 修改查询条件的关系   默认是and
        q.children.append(('title__contains','三国演义'))  # 往列表中添加筛选条件 ,接收一个元祖(字段,值)
        q.children.append(('price__gt',444))  # 往列表中添加筛选条件
        res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
        print(res)

      双下条件:

    __exact 精确等于 like 'aaa'
     __iexact 精确等于 忽略大小写 ilike 'aaa'
     __contains 包含 like '%aaa%'
     __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
    __gt 大于
    __gte 大于等于
    __lt 小于
    __lte 小于等于
    __in 存在于一个list范围内
    __startswith 以...开头
    __istartswith 以...开头 忽略大小写
    __endswith 以...结尾
    __iendswith 以...结尾,忽略大小写
    __range 在...范围内
    __year 日期字段的年份
    __month 日期字段的月份
    __day 日期字段的日
    __isnull=True/False
  • 相关阅读:
    VS 2005 RDLC报表实现WEB客户端打印(2)
    VS 2005 RDLC报表实现WEB客户端打印(1)
    封装就是一个包装,将包装的内外分为两个空间
    以count或是sum为条件的查询
    DbRulesAuthorizationProvider for .net 2.0
    Asp.net Ajax 'Sys'未定义
    广州网球场地名录
    谷歌 寄语
    深圳市网球场地一览表
    .net 2.0 串口通讯一小例
  • 原文地址:https://www.cnblogs.com/aizhinong/p/12305640.html
Copyright © 2011-2022 走看看