django之ORM操作

作者: 清风徐来_简 | 来源:发表于2019-04-25 18:27 被阅读0次

    Django 中有一个强大的功能,就是ORM,他可以不写sql语句,使用python语法,即可操作数据库。当然也有自己的书写规则。大概看一下django中的ORM的使用规则。

    前奏

    • 在settings中配置,可显示sql语句:
      # 显示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',
              },
          }
      }
      
    • 加载环境,以单文件运行
      import os
      
      if __name__ == '__main__':
          os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")  # mysite为自己的项目中settings的父级目录
          import django
          django.setup()
      

    一、单个表的增删改查

    表:
    class User(models.Model):
        username=models.charFiled(max_lenth=255)
        password=models.charFiled(max_lenth=255)
    
    创建:User.objects.create(username='zhangsan',password='123')
    查询:objs = User.objects.all()
    删除:objs = bjects.filter('id=1')
          objs.delete()
    更新:obj = objs[0]
          obj.username = "new_name"
          obj.save()
    

    接下来看一下ORM中其他的一些查询语句。

    为什么查询那么重要?
    操作数据库,简单来说就是对数据进行增删改查,在数据的增删改查四步操作中,只有增加不用查询,删除、更改 都是在查询出结果的前提下才能进行,所以ORM查询尤为重要。

    举个简单的例子,来练习一下 django的ORM查询语句 。

    二、常见的单表查询(13种)

    QuerySet 对象的形成:
    按照需求执行sql语句,从数据库查询出一个表,
    表里的每个记录封装成对象,每个字段封装成属性,
    而这个表就可以看成是QuerySet对象。

    class Person(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        birth = models.DateField(auto_now=True)
    
        def __str__(self):
            return '<Person obj:{}--{}>'.format(self.name,self.id)
    
        # class Meta:
        #     ordering = ('id',)
        # 为此类指定默认排序方式。
    
    • 【1】all():返回QuerySet对像,类似于列表的东西,查询所有。
      ret = models.Person.objects.all()
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [<Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:钱芊芊--2>>,
      #            <Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:李莉莉--4>]>
      
    • 【2】get():返回一个对象,找不到或找到多个报错。
      ret = models.Person.objects.get(id=3)  # 【此刻执行了sql语句】
      print(ret)
      # (0.001) SELECT `app01_person`.`id`, `app01_person`.`name`, `app01_person`.`age`, `app01_person`.`birth` FROM `app01_person` WHERE `app01_person`.`id` = 3; args=(3,)
      # <Person obj:孙笋笋--3>
      
    • 【2.1】 only():【使用only可以降低查询压力,增加查询速度】
      ret = models.Person.objects.only('name').get(id=3)  # 【此刻执行了sql语句】
      print(ret)
      # (0.001) SELECT `app01_person`.`id`, `app01_person`.`name` FROM `app01_person` WHERE `app01_person`.`id` = 3; args=(3,)
      # <Person obj:孙笋笋--3>
      
    • 【3】filter():返回QuerySet,包含符合条件的所有对象,查不到就是空的QuerySet对象<QuerySet []>
      ret = models.Person.objects.filter(id=3)
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [<Person: <Person obj:孙笋笋--3>>]>
      # ret = models.Person.objects.filter(id=3)[0]    # filter的时候没有执行sql语句,filter[0]的时候,执行了sql
      
    • 【4】exclude():返回QuerySet,和filter相反。
      ret = models.Person.objects.exclude(id=3)
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [<Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:钱芊芊--2>>,<Person: <Person obj:李莉莉--4>]>,
      
    • 【5】values():返回QuerySet,里面是字典
      ret = models.Person.objects.values()
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [{'id': 1, 'name': '赵昭昭', 'age': 20, 'birth': datetime.date(1998, 8, 5)},
      #            {'id': 2, 'name': '钱芊芊', 'age': 18, 'birth': datetime.date(2000, 8, 6)},
      #            {'id': 3, 'name': '孙笋笋', 'age': 16, 'birth': datetime.date(2002, 8, 6)},
      #            {'id': 4, 'name': '李莉莉', 'age': 22, 'birth': datetime.date(1996, 6, 8)} ]>
      
      ret = models.Person.objects.values('name', 'age')  # 指定字段就只显示字段的内容,找不到指定字段报错。
      print(ret)
      # <QuerySet [{'name': '赵昭昭', 'age': 20}, {'name': '钱芊芊', 'age': 18},
      #            {'name': '孙笋笋', 'age': 16}, {'name': '李莉莉', 'age': 22}]>
      
    • 【6】value_list():返回QuerySet,里面是元组,不包括健
      ret = models.Person.objects.values_list()
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [(1, '赵昭昭', 20, datetime.date(1998, 8, 5)),
      #            (2, '钱芊芊', 18, datetime.date(2000, 8, 6)),
      #            (3, '孙笋笋', 16, datetime.date(2002, 8, 6)),
      #            (4, '李莉莉', 22, datetime.date(1996, 6, 8))]>
      
      ret = models.Person.objects.values_list('age', 'name')
      print(ret)
      # <QuerySet [(20, '赵昭昭'), (18, '钱芊芊'), (16, '孙笋笋'), (22, '李莉莉')]>
      
      ret = models.Person.objects.values_list('age')
      print(ret)
      # <QuerySet[(20,), (18,), (16,), (22,)]>
      
      【flat=True】:将单个字段的数据直接放到列表里面(只有一个字段时才可用)
      ret = models.Person.objects.values_list('age', flat=True)
      print(ret)
      # <QuerySet [20, 18, 16, 22]>
      
    • 【7】order_by():按某字段排序,可反序,可按多字段排序
      ret = models.Person.objects.all().order_by('-id')
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [<Person: <Person obj:李莉莉--4>>, <Person: <Person obj:孙笋笋--3>>,
      #            <Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:赵昭昭--1>>]>
      
    • 【8】reverse():对排序后(使用了order_by)的QuerySet进行反转。(类中设置了默认排序也可以用)
      ret = models.Person.objects.all().order_by('-age').reverse()
      print(ret)  # 【此刻执行了sql语句】
      # <QuerySet [<Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:钱芊芊--2>>,
      #            <Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:李莉莉--4>>]>      
      #  年龄:16,18,20,22
      
    • 【9】distinct():去重
    • 【10】count():对QuerySet对象进行计数。
      ret = models.Person.objects.all().count()  # 【此刻执行了sql语句】
      print(ret)
      # 4
      
    • 【11】first():取QuerySet中的第一个元素。
      ret = models.Person.objects.all().first()  # 【此刻执行了sql语句】
      #  ret = models.Person.objects.first() 可不写,默认全部
      print(ret)
      # <Person obj:赵昭昭--1>
      
    • 【12】last():取QuerySet中的最后一个元素。
    • 【13】exists():如果QuerySet包含数据,就返回True,否则返回False
      ret = models.Person.objects.filter(id=1).exists()  # 【此刻执行了sql语句】
      print(ret)
      # True
      ret = models.Person.objects.filter(id=10).exists()
      print(ret)
      # False
      
    • 返回QuerySet对象的有 (QuerySet对象有个.query属性,可以查看sql语句。返回 QuerySet对象的方法,都没有真正执行sql语句。当 print QuerySet对象,或者显示QuerySet对象的结果时,才执行了sql):

      1.all()               2.filter()        3.exclude()       4.values()
      5.values_list()       6.order_by()      7.reverse()       8.distinct()
      
    • 返回具体对象的方法有:

      1.get()            2.first()             3.last()
      
    • 返回数字的方法有:

      1.count()
      
    • 返回布尔值的方法有:

      1.exists()
      

    三、单表查询的双下划线方法

    • 【查询 id = 1 的】
      ret = models.Person.objects.filter(id=1)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:赵昭昭--1>>]>
      """
      
    • 【查询 id > 1 的】( greater than )
      ret = models.Person.objects.filter(id__gt=1)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 id <3 的】( less than )
      ret = models.Person.objects.filter(id__lt=3)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:钱芊芊--2>>]>
      """
      
    • 【查询 id >=3 的】( equal )
      ret = models.Person.objects.filter(id__gte=3)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 id <=3 的】
      ret = models.Person.objects.filter(id__lte=3)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:孙笋笋--3>>]>
      """
      
    • 【查询 2 <= id <= 4 的】
      ret = models.Person.objects.filter(id__gte=2, id__lte=4)
      print(ret)
      """
      <QuerySet [<Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 id 在 。。。里的】
      ret = models.Person.objects.filter(id__in=[1, 2, 4])
      print(ret)
      """
      <QuerySet [<Person: <Person obj:赵昭昭--1>>, <Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 id 不在。。。里的】
      ret = models.Person.objects.exclude(id__in=[1, 2, 4])
      print(ret)
      """
      <QuerySet [<Person: <Person obj:孙笋笋--3>>]>
      """
      
    • 【查看某字段中包含。。。字眼的】( 找不到为空 )
      ret = models.Person.objects.filter(name__contains='赵')
      # ret = models.Person.objects.filter(name__icontains='h') 此项是英文不区分大小写。
      print(ret)
      """
      <QuerySet [<Person: <Person obj:赵昭昭--1>>]>
      """
      
    • 【查询 id 在。。。范围内】2,3,4
      ret = models.Person.objects.filter(id__range=[2, 4])
      print(ret)
      """
      <QuerySet [<Person: <Person obj:钱芊芊--2>>, <Person: <Person obj:孙笋笋--3>>, <Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 某字段以。。。为开头的】
      ret = models.Person.objects.filter(name__startswith='钱')
      # models.Person.objects.filter(name__istartswith="v") # istartswith大小写不敏感
      print(ret)
      """
      <QuerySet [<Person: <Person obj:钱芊芊--2>>]>
      """
      
    • 【查询 某字段以。。。为结尾的】( iendswith 模糊查询 )
      ret = models.Person.objects.filter(name__endswith='莉')
      print(ret)
      """
      <QuerySet [<Person: <Person obj:李莉莉--4>>]>
      """
      
    • 【查询 关于年,月,日 的】
      ret = models.Person.objects.filter(birth__year=1998)
      ret = models.Person.objects.filter(birth__month=6)
      ret = models.Person.objects.filter(birth__day=10)
      # mysql 数据库可以用这样逗号隔开and的 方式。用django自带的数据库可能不支持。
      ret = models.Person.objects.filter(birth__year=1998, birth__month=6)  
      ret = models.Person.objects.filter(birth__contains='1998-06')
      print(ret)  # 有警告,但是可以查出来。
      

    四、有外键关系的查询

    • 先定义三个模型类,出版社 <---1对多---> 书籍 <---多对多---> 作者。
      from django.db import models
      
      class Publisher(models.Model):
          name = models.CharField(max_length=32)
      
      class Book(models.Model):
          title = models.CharField(max_length=32)   
          publisher = models.ForeignKey(to='Publisher')  
          # publisher = models.ForeignKey(to='Publisher',related_name='books')
          # publisher = models.ForeignKey(to='Publisher',related_name='books',related_query_name='xx')
          # 这个related_name 反向查询,基于对象时用 【和下面【↓】的对应】。
          # 这个related_query_name 【反向查询,基于字段】时用。
          price = models.DecimalField(max_digits=5,decimal_places=2,null=True)
      
      class Author(models.Model):
          name = models.CharField(max_length=32)
          books = models.ManyToManyField(to='Book')     
      
    • 查询时先看清楚是正向还是反向,看清是基于对象的查询还是基于字段的查询。


      外键的正反向查询.png

    1,【正向查询】---> 从多往1找(一般外键都设在多的一方)

    • 基于对象查询
      book_obj = models.Book.objects.filter(title='北京生活')[0] 
      #【先有一个对象,拿出一本书,再查有关书的一些东西】
      print(book_obj.title)   # 书的名字(没有设外键的字段)
      print(book_obj.publisher)  # Publisher object 出版社对象(设外键的字段)
      print(book_obj.publisher.name)  # 北京出版社(跨表查询)
      
    • 基于字段查询 (跨表查询)(不是本表中的字段,是关联表中的字段)
      ret = models.Book.objects.filter(publisher__name='北京出版社')  
      # 站在书籍的角度,查询'北京出版社'出版的所有书籍
      print(ret)
      

    2,【反向查询】---> 从1往多找

    • 基于对象查询
      publisher_obj = models.Publisher.objects.get(name='北京出版社')  # 拿到一个出版社对象
      print(type(publisher_obj.book_set))    # "关联管理器"
      print(publisher_obj.book_set.all())    # "关联管理器".all()查询出版社出版的所有书籍。
      
      # Book表中的:
      # publisher = models.ForeignKey(to='Publisher',related_name='books')
      # print(publisher_obj.books.all()) (【和上面【↑】对应】,如果关联对象的相关字段写了related_name='books',本语句就可这样写。)
      
      # pub_obj = models.Publisher.objects.first()  # 拿到北京出版社
      # pub_obj.book_set.create(title='北京生活')  # 利用管理对象,创建书籍(为本出版社添加书籍,但是书籍没有作者)
      
    • 基于字段查询 (跨表查询)
      ret = models.Publisher.objects.filter(book__title="北京生活")  # 查询"北京生活"的出版社。
      print(ret)
      # 如果上面加了related_name = 'bookssss',那么就得写成(bookssss__title="北京生活"【和上面【↑】对应】)。
      # 如果上面在加了related_name = 'books'之后,又加了 related_query_name='xx',就得写(xx__title="北京生活")。
      # 也就是说:
      #   如果外键字段只定义了 related_name = 'books' ,那么反向查询时,不管基于对象还是基于字段都可以使用 books 名称代替。
      #   如果外键字段定义了 related_name = 'books' ,又定义了 related_query_name='xx' 那么基于字段的反向查询时只能使用 xx__title 名称代替。
      
      '''外键的"关联管理器",在被关联那一边,反向查找时可用,是book_set(表名_set),可起别名'''
      
      # 如果把出版社的所有书籍都删了,也就是删除了有关书籍和这个出版社的对应关系,对于书籍而言,出版社就为空了。
      # 如果想要在多对一的关系中,基于1的一面删除多,就得在多的一面设置可以为空。
      

    五、多对多关系的增删改查

    1,【正向查询】

    • 基于对象
      多对多的正向查询.png
      author_obj = models.Author.objects.first()
      print(author_obj.name)  # 作者的姓名  李白
      print(author_obj.books)  # "关联管理器"
      
      # print(author_obj.books.all())
      # author_obj.books.create(title='一起来学习',publisher_id=5)   # "关联管理器".create()创建book对象  
      # author_obj.books.add(10,11)  # 给作者添加几本书,之前在出版社创建了几本书,现在是给作者增加几个关联对象
      # author_obj.books.remove(12,13)  # 和add相反,去除几个书籍。
      # author_obj.books.clear()  # 清空
      
      # "关联管理器".add(*args),添加几个关联,(前提是有这几本书)相当于在第三张关联表中,增加了几个关联。
      # 和 author_obj.books.set([]) 不同:
      #        set是创建对象时或者创建对象后,给多对多字段设置属性,可以是id列表,可以是QuerySet
      #        add是有了对象,给对象增加属性,可以是id,可以是对象。如果是QuerySet,必须打散
      
      # booklist = models.Book.objects.filter(author__id=1)
      # print(booklist)
      # print(*booklist)
      # author_obj.books.remove(*booklist)
      
      # publisher_obj = models.Publisher.objects.get(id=1)
      # booklist2 = publisher_obj.book_set.all()
      # print(publisher_obj)
      # print(booklist2)
      # author_obj.books.set(booklist2)
      
      '''多对多的"关联管理器",在关联那一边,名字为,设置了多对多关系的字段名books'''
      

    六、聚合与分组

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

    1、聚合函数

    • 可自己写名称,默认是以 字段__聚合函数 为名称
      avg = models.Book.objects.aggregate(Avg('price'))
      print(avg)  # {'price__avg': 80.0}
      
      avg = models.Book.objects.aggregate(平均=Avg('price'))
      print(avg)  # {'平均': 80.0}
      
      ret = models.Book.objects.aggregate(Sum('price'),Max('price'),Min('price'),Count('id'))
      print(ret)  # {'price__sum': Decimal('1040.00'), 'price__max': Decimal('140.00'),
                  # 'price__min': Decimal('20.00'), 'id__count': 13}
      

    2、分组

    • 【统计书的作者个数】 书 <------> 作者

      ret = models.Book.objects.annotate(Count('author')).values()
      for i in ret:
          print(i)
      
    • 【出版社最便宜的书的价格】 出版社 <------> 书

      ret = models.Publisher.objects.annotate(Min('book__price')).values()
      for i in ret :
          print(i)
      
    • 【作者个数大于1的书】 作者 <------> 书

      ret = models.Book.objects.annotate(num=Count('author')).filter(num__gt=1).values()
      for i in ret:
          print(i)
      
    • 【查询各个作者出了几本书】 作者 <------> 书

      ret = models.Author.objects.annotate(Count('books')).values()
      for i in ret:
          print(i)
      
    • 【查询各个作者出的书的总价格】 作者 <------> 书

      ret = models.Author.objects.annotate(Sum('books__price')).values()
      for i in ret:
          print(i)
      
      '''annotate前面是什么就按什么分组,没有默认是以id为准'''
      

    七、F查询、Q查询

    class Book(models.Model):
        title = models.CharField(max_length=32)
        publisher = models.ForeignKey(to='Publisher') 
    
        price = models.DecimalField(max_digits=5,decimal_places=2,null=True)
        # 此字段为以后聚合函数使用      最大长度      小数点后长度    可以为空
        # 后加的字段,需要设置默认值,要不就设置可以为空
    
        kucun = models.IntegerField(default=0)
        sale = models.IntegerField(default=100)
        # 后加字段,为测试 F查询、Q查询使用
    
    from django.db.models import F, Q
    
    • 【F 查询】

      # 原来查询方法,比较时,符号后面是外界得到的条件,是提前给好的数据。
      ret = models.Book.objects.filter(id__gt=10)  # 过滤条件是跟常量比较。
      print(ret)
      # 想要在表中自己和自己的数据比较就得用 F 查询
      
      # 【查询库存数小于出售数的】
      ret = models.Book.objects.filter(kucun__lt=F('sale'))
      for i in ret:
          print(i)
          print(i.title, i.kucun, i.sale)
      
      # 原来的方法,修改对象的属性时,是这样操作:
      book_obj = models.Book.objects.get(title='红楼梦')
      book_obj.title = '葫芦娃'
      book_obj.save()
      
      # 新的修改方法:QuerySet对象.update(字段=‘’)
      models.Book.objects.filter(title='葫芦娃').update(title='金刚葫芦娃')
      
      #【给所有书的库存增加数量】
      models.Book.objects.all().update(kucun=F('kucun')+100)
      
      #【给书籍名字统一加字符串】
      from django.db.models.functions import Concat
      from django.db.models import Value
      models.Book.objects.all().update(title=Concat(F('title'),Value('(第一版)')))
      
    • 【Q 查询】

      # 原来查询两边的查询:
      ret = models.Book.objects.filter(id__gt=3, id__lt=6)  # 4,5
      print(ret)
      ret = models.Book.objects.exclude(id__gt=3, id__lt=6)  # 没有4,5
      print(ret)
      ret = models.Book.objects.exclude(id=3)  # 没有3
      print(ret)
      
      # 现在查询两边的查询:
      ret = models.Book.objects.filter(Q(id__gt=3) & Q(id__lt=6))  # 4,5,并且
      print(ret)
      ret = models.Book.objects.filter(Q(id__lt=3) | Q(id__gt=6))  # 小于3,大于6,没有3,4,5,6,或
      print(ret)
      ret = models.Book.objects.filter(~Q(id=3))  # 没有3
      print(ret)
      ret = models.Book.objects.filter(~Q(id=3), id__lt=5)  # 小于5,且没有3【注意,Q放前面】
      print(ret)
      
      # Q 查询的另一种用法。
      q = Q()  # 实例出一个对象。
      q.children.append(('title', '西游记'))  # 元组里放字符串
      obj = models.Book.objects.filter(q)
      print(obj)
      
      q1 = Q()  # 空的Q对象,等同于all().
      q1.connector = 'or'  # 将查询条件改成“或”,默认是“与”
      q1.children.append(('title', '西游记'))
      q1.children.append(('price' + '__icontains', 20)) # 可添加多个搜索条件,支持模糊查询。
      ret = models.Book.objects.filter(q1)
      print(ret) 
      

    八、面试题

    from django.db import models
    
    
    class WfModel(models.Model):
        """
        工作流
        """
        model_id = models.AutoField(primary_key=True)  # 主键ID
        model_name = models.CharField(max_length=255)  # 工作流名称
        create_time = models.DateTimeField(auto_now_add=True)  # 添加时间
    
        def __str__(self):
            return "ID为%s的%s号" % (self.model_id, self.model_name)
    
    
    class WfStep(models.Model):
        """
        工作流步骤
        """
        step_id = models.AutoField(primary_key=True)  # 主键ID
        model = models.ForeignKey(WfModel, models.DO_NOTHING)  # 流程ID
        step_name = models.CharField(max_length=255)  # 步骤名称
    
        def __str__(self):
            return self.step_name
    
    
    class WfStepCheck(models.Model):
        """
        工作节流点人员表
        """
        check_id = models.AutoField(primary_key=True)  # 主键
        step = models.ForeignKey(WfStep, models.DO_NOTHING)  # 步骤ID
        check_user_id = models.IntegerField()  # 角色ID或用户ID
        is_design = models.BooleanField(default=1)  # 是否设计;1是;0否;
    
        def __str__(self):
            return "%s的%s号人员,check_id为%s" % (self.step, self.check_user_id, self.check_id)
    
    • 【1】、如上3个实体表,其中知道实体 WfModel 的 model_id 值为:[1, 2, 3],要查询 WfStepCheck 中 is_design 的值,请用 django 的 orm 或 sql 写出查询语句
    # sql = "select step_id from app_wfstep where model_id in (1,2,3)"
    sql = "select is_design from app_wfstepcheck where step_id in(select step_id from app_wfstep where model_id in (1,2,3))"
    
    from django.db import connection
    
    cursor = connection.cursor()
    cursor.execute(sql)
    row = cursor.fetchall()
    print(row)
    
    或者使用以下的orm查询语句↓ (执行一次数据库查询)
    objects = WfStepCheck.objects.select_related('step').filter(step__model__model_id__in=[1, 2, 3]).values('is_design')
    print(objects)
    
    • 【2】、实体 WfModel 中 model_id 值为:[1, 2, 3],要更新 WfStepCheck 中 is_design 的值为 False,请用 django 的 orm 或 sql 写出更新语句
    objects = WfStepCheck.objects.filter(step__model__model_id__in=[1, 2, 3])
    #print(objects)
    #如果单独查询,直接print的话会执行多次sql,但是如果使用objects.update()会执行一次sql。
    #所以:如果是更新的话,不用使用select_related,但要是查询的时候建议使用select_related,减少数据库查询次数。
    objects.update(is_design=0)
    
    • 【3】、通过 WfModel 的 model_id 为3的条件,查询 WfStepCheck 的信息,函数为 get_wf_check(),此函数是否有问题,为什么?
    def get_wf_check():
        """获取步骤的审批人员信息"""
        step_check = []
        for item in WfModel.objects.filter(model_id=3):
            # print("item-->",item)
            for step in WfStep.objects.filter(model=item):
                # print("step-->",step)
                for stepcheck in WfStepCheck.objects.filter(step=step):
                    # print("stepcheck-->",stepcheck)
                    step_check.append(stepcheck)
        return step_check
    
    ret = get_wf_check()
    print(ret)
    
    # for obj in ret:
    #     print(obj.check_id, obj.check_user_id, obj.step, obj.is_design)
    

    这样不好,他会多次去查询数据库,增加数据库压力。最好这样,只查询一次:

    ret = WfStepCheck.objects.select_related('step').filter(step__model__model_id=3)
    print(ret)
    

    1,每一张表在数据库中,都是以app的名字开头
    2,外键的字段在数据库中,会自动加上_id
    3,__str__中必须返回字符串,如果想要在models类里面显示数字类的信息,需要str一下。

    相关文章

      网友评论

        本文标题:django之ORM操作

        本文链接:https://www.haomeiwen.com/subject/ysttnqtx.html