zoukankan      html  css  js  c++  java
  • 十三 .Django(ORM表高级操作)

    一 .ORM连表高级操作

     https://www.cnblogs.com/dangrui0725/p/9616192.html

     1.ORM分组操作用于实现聚合group by查询

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

    res=models.Emp.objects.filter(age='22').order_by('id') # asc print(res) # <QuerySet [<Emp: Emp object (3)>, <Emp: Emp object (4)>]> res=models.Emp.objects.filter(age='22').order_by('-id') # desc print(res) # <QuerySet [<Emp: Emp object (4)>, <Emp: Emp object (3)>]> res=models.Emp.objects.filter(id=1).values('name').annotate(c=Count('age')) # <QuerySet [{'name': '张三', 'c': 1}]> res= models.Emp.objects.filter(id=2).values('name').annotate(c=Count('age')) # <QuerySet [{'name': '李四', 'c': 1}]> print(res.query) #SELECT `app01_emp`.`name`, COUNT(`app01_emp`.`age`) AS `c` FROM `app01_emp` WHERE `app01_emp`.`id` = 2 GROUP BY `app01_emp`.`name` ORDER BY NULL res=models.Emp.objects.values("nid_id").annotate(cc=Count("id")).filter(age__gt=2) print(res) #<QuerySet [{'nid_id': 1, 'cc': 2}, {'nid_id': 2, 'cc': 1}, {'nid_id': 3, 'cc': 1}, {'nid_id': 4, 'cc': 1}]> <QuerySet [{'nid_id': 1, 'cc': 2}, {'nid_id': 2, 'cc': 1}, {'nid_id': 3, 'cc': 1}, {'nid_id': 4, 'cc': 1}]> print(res.query)#SELECT `app01_emp`.`nid_id`, COUNT(`app01_emp`.`id`) AS `cc` FROM `app01_emp` WHERE `app01_emp`.`age` > 2 GROUP BY `app01_emp`.`nid_id` ORDER BY NULL res=models.Emp.objects.filter(id__gt=2).values("nid_id").annotate(cc=Count("id")).filter(age__gt=2) print(res) <QuerySet [{'nid_id': 1, 'cc': 1}, {'nid_id': 3, 'cc': 1}, {'nid_id': 4, 'cc': 1}]> print(res.query)#SELECT `app01_emp`.`nid_id`, COUNT(`app01_emp`.`id`) AS `cc` FROM `app01_emp` WHERE (`app01_emp`.`id` > 2 AND `app01_emp`.`age` > 2) GROUP BY `app01_emp`.`nid_id` ORDER BY NULL

      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
     

    2. F查询(更新数据时获取原数据值)

    在之前的所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
    
    Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值
    查询评论数大于收藏数的书籍
    
    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)

      models.Emp.objects.all().update(age=F("age")+22)

    3. Q查询(用于构造复杂条件)

    Q查询可以组合使用 “&”, “|” 操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象,Q对象可以用 “~” 操作符放在前面表示否定,也可允许否定与不否定形式的组合。
    Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
    filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象
    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(nid__gt=10)
    Q(nid=8) | Q(nid__gt=10)
    Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
    
    
    
    
    方式二:
    con = Q()
    q1 = Q()
    q1.connector = 'OR'
    q1.children.append(('id', 1))
    q1.children.append(('id', 10))
    q1.children.append(('id', 9))
    q2
    = Q() q2.connector = 'OR' q2.children.append(('c1', 1)) q2.children.append(('c1', 10)) q2.children.append(('c1', 9)) con.add(q1, 'AND') con.add(q2, 'AND')
    models.Tb1.objects.filter(con)
    from django.db.models import Q
    
    print(Book.objects.filter(Q(id=3))[0])  # 因为获取的结果是一个QuerySet,所以使用下标的方式获取结果
    print(Book.objects.filter(Q(id=3)|Q(title="Go"))[0])  # 查询id=3或者标题是“Go”的书
    print(Book.objects.filter(Q(price__gte=70)&Q(title__startswith="J")))  # 查询价格大于等于70并且标题是“J”开头的书
    print(Book.objects.filter(Q(title__startswith="J") & ~Q(id=3)))  # 查询标题是“J”开头并且id不是3的书
    print(Book.objects.filter(Q(price=70)|Q(title="Python"), publication_date="2017-09-26"))  # Q对象可以与关键字参数查询一起使用,必须把普通关键字查询放到Q对象查询的后面
    from django.db.models import Q
    
    con = Q()
    q1 = Q()
    q1.connector = "AND"
    q1.children.append(("email", "123@qq.com"))
    q1.children.append(("password", "abc123"))
    
    q2 = Q()
    q2.connector = "AND"
    q2.children.append(("username", "abc"))
    q2.children.append(("password", "xyz123"))
    
    con.add(q1, "OR")
    con.add(q2, "OR")
    
    obj = models.UserInfo.objects.filter(con).first()
    
    # 查询email=123@qq.com和password=abc123 或者 username=abc和password=xyz123的用户信息
        aa={
              "id":1,
              "name":"李四"
          }
        res=models.Emp.objects.filter(**aa)
        print(res)

     4. Django原生sql

        from django.db import connection, connections
        cursor = connection.cursor()  # cursor = connections['default'].cursor()  默认是default数据库 也可是其他数据库
        cursor.execute("""SELECT * from auth_user where id = %s""", [1])
        row = cursor.fetchone()
      # row = cursor.fetchall()

    DATABASES = {
        'default': { 默认数据库
            'ENGINE': 'django.db.backends.mysql',
            'NAME': "db7",    #create DATABASE Dear1;
            'USER': "root",
            'PASSWORD':'root',
            'HOST':'localhost',
            'PORT':'3306',
        },
    
       'db1': {  
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
              }
    
    }

     5 .extra 构造额外的查询条件或者映射

    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'])
      res= models.Emp.objects.extra(
              select={'new_nid':'select count(1) from  app01_emp where id>%s'},
              select_params=[1,],
              where=['age>%s'],
              params=[22,],
              order_by=['-age'],
              tables=[' app01_emp']
          )
         print(res)

    
    
     res= models.Emp.objects.extra(
             where=["id=1","name='李四'"]
          )
    
     res = models.Emp.objects.extra(
             where=["id=1 or id=%s", "name=%s"],
             params=[1,"李四"]
         )
         
      res= models.Emp.objects.filter(id__gt=2).extra(
             where=[" app01_emp.id<3"]  )
     print(res.query) #SELECT `app01_emp`.`id`, `app01_emp`.`name`, `app01_emp`.`hobby`, `app01_emp`.`age`, `app01_emp`.`nid_id` FROM `app01_emp` WHERE (`app01_emp`.`id` > 2 AND ( app01_emp.id<3))
    def find_show(request):
         res= models.Emp.objects.filter(id__gt=2).extra(
             where=[" app01_emp.id<%s"],
             params=[4,]
    
         )
         print(res.query)
    res= models.Emp.objects.filter(id__gt=2).extra(
             where=[" app01_emp.id<%s"],
             params=[4,],
             tables=["app01_emp"]
    
         )
         print(res.query)
    #SELECT `app01_emp`.`id`, `app01_emp`.`name`, `app01_emp`.`hobby`, `app01_emp`.`age`, `app01_emp`.`nid_id` FROM `app01_emp` WHERE (`app01_emp`.`id` > 2 AND ( app01_emp.id<4))
     res= models.Emp.objects.filter(id__gt=2).extra(
             where=[" app01_emp.id<%s"],
             params=[4,],
             tables=["app01_emp"],
             order_by=["app01_emp.id"]
    
         )
    print(res.query)
    
    #SELECT `app01_emp`.`id`, `app01_emp`.`name`, `app01_emp`.`hobby`, `app01_emp`.`age`, `app01_emp`.`nid_id` FROM `app01_emp` WHERE (`app01_emp`.`id` > 2 AND ( app01_emp.id<4)) ORDER BY (`app01_emp`.id) ASC
    res= models.Emp.objects.filter(id__gt=2).extra(
             where=[" app01_emp.id<%s"],
             params=[4,],
             tables=["app01_emp"],
             order_by=["app01_emp.id"],
             select={"nid":1,"sw":"select count(1) from app01_emp"}
    
         )
    print(res.query)
    
    #SELECT (1) AS `nid`, (select count(1) from app01_emp) AS `sw`, `app01_emp`.`id`, `app01_emp`.`name`, `app01_emp`.`hobby`, `app01_emp`.`age`, `app01_emp`.`nid_id` FROM `app01_emp` WHERE (`app01_emp`.`id` > 2 AND ( app01_emp.id<4)) ORDER BY (`app01_emp`.id) ASC

     6. 其他操作

    https://www.cnblogs.com/wupeiqi/articles/6216618.html
    用于distinct去重 models.UserInfo.objects.values(
    'nid').distinct() 用于排序 models.UserInfo.objects.all().order_by('-id','age') 倒序 models.UserInfo.objects.all().order_by('-nid').reverse() 仅取某个表中的数据 models.UserInfo.objects.only('username','id') 映射中排除某列数据 models.UserInfo.objects.defer('username','id') models.UserInfo.objects.filter(...).defer('username','id') 性能相关:表之间进行join连表操作,一次性获取关联的数据。 model.tb.objects.all().select_related() model.tb.objects.all().select_related('外键字段') model.tb.objects.all().select_related('外键字段__外键字段')

    执行原生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"
     models.UserInfo.objects.all().using("db2")
    如果存在,则获取,否则,创建
    defaults 指定创建时,其他字段的值
    obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})
    
    如果存在,则更新,否则,创建
    defaults 指定创建时或更新时的其他字段
    obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})
    
    
    
    批量插入
    batch_size表示一次插入的个数
        objs = [
            models.DDD(name='r11'),
            models.DDD(name='r22')
        ]
        models.DDD.objects.bulk_create(objs, 10)
    
    
    数字自增、字符串更新
       # 数字自增
        from django.db.models import F
        models.UserInfo.objects.update(num=F('num') + 1)
    
        # 字符串更新
        from django.db.models.functions import Concat
        from django.db.models import Value
    
        models.UserInfo.objects.update(name=Concat('name', 'pwd'))
        models.UserInfo.objects.update(name=Concat('name', Value('666')))
    
    
    ORM函数相关
    # ########### 基础函数 ###########
    
        # 1. Concat,用于做类型转换
        # v = models.UserInfo.objects.annotate(c=Cast('pwd', FloatField()))
    
        # 2. Coalesce,从前向后,查询第一个不为空的值
        # v = models.UserInfo.objects.annotate(c=Coalesce('name', 'pwd'))
        # v = models.UserInfo.objects.annotate(c=Coalesce(Value('666'),'name', 'pwd'))
    
        # 3. Concat,拼接
        # models.UserInfo.objects.update(name=Concat('name', 'pwd'))
        # models.UserInfo.objects.update(name=Concat('name', Value('666')))
        # models.UserInfo.objects.update(name=Concat('name', Value('666'),Value('999')))
    
        # 4.ConcatPair,拼接(仅两个参数)
        # v = models.UserInfo.objects.annotate(c=ConcatPair('name', 'pwd'))
        # v = models.UserInfo.objects.annotate(c=ConcatPair('name', Value('666')))
    
        # 5.Greatest,获取比较大的值;least 获取比较小的值;
        # v = models.UserInfo.objects.annotate(c=Greatest('id', 'pwd',output_field=FloatField()))
    
        # 6.Length,获取长度
        # v = models.UserInfo.objects.annotate(c=Length('name'))
    
        # 7. Lower,Upper,变大小写
        # v = models.UserInfo.objects.annotate(c=Lower('name'))
        # v = models.UserInfo.objects.annotate(c=Upper('name'))
    
        # 8. Now,获取当前时间
        # v = models.UserInfo.objects.annotate(c=Now())
    
        # 9. substr,子序列
        # v = models.UserInfo.objects.annotate(c=Substr('name',1,2))
    
        # ########### 时间类函数 ###########
        # 1. 时间截取,不保留其他:Extract, ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,ExtractSecond, ExtractWeekDay, ExtractYear,
        # v = models.UserInfo.objects.annotate(c=functions.ExtractYear('ctime'))
        # v = models.UserInfo.objects.annotate(c=functions.ExtractMonth('ctime'))
        # v = models.UserInfo.objects.annotate(c=functions.ExtractDay('ctime'))
        #
        # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'year'))
        # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'month'))
        # v = models.UserInfo.objects.annotate(c=functions.Extract('ctime', 'year_month'))
         # Book.objects.filter(id=2)             #取集合数据
         Book_list=Book.objects.all()          #查询所有数据
         # Book_list=Book.objects.all()[:3]      #只截取前三条数据
         # Book_list=Book.objects.all()[::-1]    #倒序去数据
         # Book_list=Book.objects.all()[::2]     #按照步长取数据
         # Book_list=Book.objects.first()        #取第一个数据
         # Book_list=Book.objects.last()         #取第最后一个数据
         # Book_list=Book.objects.get(id=2)      #条件筛选取数据   只能一条一条的数据取  不然会报错
         # Book_list=Book.objects.filter(author="李四").values("name")       #filter条件筛选取数据   返回来的数据是是字典类型
         # Book_list=Book.objects.filter(author="李四").values_list("name")    #filter条件筛选取数据   返回来的数据是列表类型
         # Book_list=Book.objects.exclude(author="李四").values("name") # 它包含了与给的筛选条件不匹配的对象 与filter()相反  
         # Book_list=Book.objects.order_by()                     # 对查询结果排序
         # Book_list=Book.objects.reverse()                      # 对查询结果反相排序
         # Book_list=Book.objects.all().values("author").distinct()         # distinct() 从结果集中删除重复记录 要加条件
         # Book_list=Book.objects.all().values("author").distinct().count()    # 意思去除重复后的 数据个数
         # Book_list=Book.objects.filter(price__gt=50).values("name","price")    # 读取大于50数据
         # Book_list=Book.objects.filter(id__gt=3).values("name","price")    # id读取大于3数据
         # Book_list=Book.objects.filter(name__icontains="P").values("name","price")    # 不区分大小写
         # print( Book_list)
         return render(request,"html_app/04mysql.html",{"book":Book_list})
         # return HttpResponse("删除成功了!!!!!!!!!!!!!!!!!!!")
  • 相关阅读:
    Lucene.Net
    授权
    测试
    Upgrade ASP.NET 1.1 To ASP.NET 2.0 Cookie
    Highlight
    缓存
    base
    System.Environment.UserDomainName 为什么不返回 当前的 Domainname
    英语骂人一百句
    比较动态调用代码
  • 原文地址:https://www.cnblogs.com/lovershowtime/p/11359353.html
Copyright © 2011-2022 走看看