day 53

day 53 模型层

01.ORM查询

  1. 在后端直接对models层进行测试

    1. 方式一:直接使用应用下的tests.py文件

      # 去manage.py拷贝前四行代码
      # 自己再书写两行就行了
      import os
      if __name__ == "__main__":
      	os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings")
      	import django
      	django.setup()
      	# 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试
      	from app01 import models
      
    2. 方式二:自己新建一个py文件内部也写上方式一的代码

  2. 单表操作

    1. 创建数据

      1. create方法

        book_obj = models.Books.objects.create(title='三国演义',price=123.23,publish_date='2019-11-11')
        # 日期格式可以接收字符串,还可以传日期对象
        from datetime import date
        ctime = date.today()
        book_obj = models.Books.objects.create(title='红楼梦', price=888.99, publish_date=ctime)
        
      2. 利用对象的绑定方法save

        book_obj = models.Books(title='西游记',price=666.66,publish_date='2000-1-21')
        book_obj.save()
        
    2. 修改数据

      1. 利用queryset对象的update方法

        res = models.AuthorDetail.objects.filter(id=4).update(phone=121212)
        
        # 只要是queryset对象就可以无限制的调用queryset方法
        res = models.Books.objects.filter(pk=1).filter().filter().filter().filter()
        # 只要是queryset对象都可以.query查看当前结果对应的sql语句
        res.query
        SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1 
        
      2. 对象.字段=修改值(会将对象的所有字段都修改一遍,不推荐使用)

        obj = models.Author.objects.filter(id=2).first()
        obj.age=24
        obj.save()
        
    3. 删除数据

      1. 利用queryset对象的delete方法

        models.Books.objects.filter(pk=3).delete()
        
      2. 对象.delete()

        book_obj = models.Books.objects.get(pk=3)
        book_obj.delete()
        
        get和filter区别
        	1.filter获取到的是一个queryset对象 类似于一个列表
        	2.get获取到的直接就是数据对象本身
        	当条件不存在的情况下
        	filter不报错直接返回一个空  推荐使用filter方法
        	get直接报错 所以不推荐使用get方法
        
    4. 查询数据

      orm语句的默认都是惰性查询

      只有当真正使用数据时才会执行sql语句

      1. all(): 查询所有结果(返回queryset对象)

        res = models.Books.objects.all()
        
      2. filter(**kwargs): 它包含了与所给筛选条件相匹配的对象(相当于sql语句中的where)(返回queryset对象)

        res = models.Books.objects.filter(pk=1,title='三')  # 支持多个参数 并且是and关系
        
      3. get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(不推荐使用)

        res = models.Books.objects.get(title='西游记')
        res1 = models.Books.objects.filter(title='西游记')
        
      4. first(): 返回queryset中的第一个对象,返回结果为数据对象

        res = models.Books.objects.filter(title='西游记').first()
        
      5. last(): 返回queryset中的最后一个对象,返回结果为数据对象

        res = models.Books.objects.filter(title='西游记').last()
        
      6. count(): 统计queryset中数据的个数,返回数字int

        num = models.Books.objects.count()
        
      7. values(*field): 获取数据对象中指定的字段值,可以有多个(返回一个ValueQuerySet——一个特殊的QuerySet(列表套字典),运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列)

        res = models.Books.objects.values('title','price')
        <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>
        
      8. values_list(*field): 它与values()非常相似,它返回的是一个元组序列(列表套元组),values返回的是一个字典序列

        res = models.Books.objects.values_list('title','price')
        <QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
        
      9. order_by(*field): 对查询结果,按照指定的字段排序(默认升序)

        res = models.Books.objects.order_by('price')  # 默认是升序
        res1 = models.Books.objects.all().order_by('price')  # 默认是升序   两者等价 下面的方式 语义更明确
        
      10. reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。

        res = models.Books.objects.all().order_by('price').reverse()
        res1 = models.Books.objects.all().order_by('-price')  # 也是降序效果
        
      11. exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象(排除符合条件的数据)

        res = models.Books.objects.all().exclude(title='三国演义')
        
      12. exists(): 如果QuerySet包含数据,就返回True,否则返回False

        res = models.Books.objects.filter(pk=1).exists()
        # 该方法其实不需要使用  因为数据本身自带布尔值
        
      13. distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)(数据必须要是完全相同的,包括主键)

        res = models.Books.objects.values('title','price').distinct()
        
    5. 如果想要查看所有的sql语句

      # 放在settings.py中
      # 在涉及到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. 双下划线查询

    1. 大于,小于,大于等于,小于等于

      查询价格大于500的书籍
      res = models.Books.objects.filter(price__gt=500)
      查询价格小于400 的书籍
      res = models.Books.objects.filter(price__lt=400)
      查询价格大于等于500
      res = models.Books.objects.filter(price__gte=500)
      查询价格小于等于500的书籍
      res = models.Books.objects.filter(price__lte=500)
      
    2. 是a或b或c

      # 查询价格是222.66或者444.22或者500的书籍
      res = models.Books.objects.filter(price__in=[222,444,500])
      
    3. 范围查询

      # 查询价格在200到800之间的书籍
      res = models.Books.objects.filter(price__range=(200,800))  # 顾头顾尾
      
    4. 日期查询

      # 查询出版日期是2019年的书籍
      res = models.Books.objects.filter(publish_date__year='2019')
      # 查询出版日期是1月份的书籍
      res = models.Books.objects.filter(publish_date__month='1')
      
    5. 模糊查询

      """
      MySQL中的模糊查询
          关键字 like
              模糊匹配的符号
                  %:匹配任何个数的任意字符
                  _:匹配一位任意的字符
      """
      
      # 查询书籍是以三开头的书
      res = models.Books.objects.filter(title__startswith='三')
      # 查询书籍是以义结尾的书
      res = models.Books.objects.filter(title__endswith='1')
      # 查询书籍名称中包含游字的书籍
      res = models.Books.objects.filter(title__contains='游')
      # 查询书籍名称中包含字母p的书籍
      res = models.Books.objects.filter(title__contains='p')  # 默认区分大小写
      res = models.Books.objects.filter(title__icontains='p')  # 忽略大小写 加i
      
  4. 图书管理表设计

    1. auto_now 和 auto_now_add
  5. (一对多)外键字段的增删改查

    1. models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)
      
      publish_obj = models.Publish.objects.filter(pk=2).first()
      models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj)
      # models中的外键字段接收关联对象,自动将pk主键值绑定
      
    2. models.Publish.objects.filter(pk=1).delete()  # 默认就是级联删除 级联更新
      # 会自动将关联数据全部删除
      
    3. # 第一种
      models.Book.objects.filter(pk=1).update(publish_id=2)
      # 第二种
      publish_obj = models.Publish.objects.filter(pk=1).first()
      models.Book.objects.filter(pk=1).update(publish=publish_obj)
      
  6. (多对多)外键字段的增删改查(第三张表)

      1. add
      book_obj = models.Book.objects.filter(pk=2).first()
      # 点外键字段 可能会直接获取到外键关联的数据对象
      book_obj.authors.add(1,2)  # 在第三张表里面给书籍绑定一个主键为1,2的作者
      
      author_obj = models.Author.objects.filter(pk=1).first()
      author_obj1 = models.Author.objects.filter(pk=2).first()
      book_obj.authors.add(author_obj,author_obj1)  # 该方法也可以传对象
      
      1. remoeve 既可以传数字 也可以穿对象,并且都支持传多个 不需要迭代

        book_obj = models.Book.objects.filter(pk=2).first()
        book_obj.authors.remove(1,2)
        author_obj = models.Author.objects.filter(pk=1).first()
        author_obj1 = models.Author.objects.filter(pk=2).first()
        book_obj.authors.remove(author_obj,author_obj1)
        
      2. clear clear清空书籍相关所有记录 括号内不需要传递参数

        book_obj = models.Book.objects.filter(pk=2).first()
        book_obj.authors.clear()
        
      1. set (内部放可迭代对象)
      book_obj = models.Book.objects.filter(pk=2).first()
      book_obj.authors.set((1,3))
      book_obj.authors.set([1,])
      
      author_obj = models.Author.objects.filter(pk=1).first()
      author_obj1 = models.Author.objects.filter(pk=2).first()
      book_obj.authors.set((author_obj,author_obj1))
      
  7. 跨表查询

    1. 子查询,基于对象

      1.查询书籍主键为2的出版社名称
      book_obj = models.Book.objects.filter(pk=2).first()
      print(book_obj.publish)  # 出版社对象
      print(book_obj.publish.name)
      
      2.查询书籍主键为4的作者姓名
      book_obj = models.Book.objects.filter(pk=4).first()
      print(book_obj.authors)  # app01.Author.None
      print(book_obj.authors.all())
      # 当正向查询点击外键字段数据有多个的情况下 需要.all()
      
      3.查询作者是jason的手机号码
      author_obj = models.Author.objects.filter(name='jason').first()
      print(author_obj.author_detail)
      print(author_obj.author_detail.phone)
      
    2. 联表查询(基于双下划线)

      # 正向
      res = models.Book.objects.filter(pk=2).values('publish__name')  # 写外键字段就相当于已经跨到外键字段所关联的表
      # 你想要改表的哪个字段信息 你只需要加__获取即可
      # 反向
      res = models.Publish.objects.filter(book__pk=2).values('name')  # 还是在models.的表中
      
  8. 聚合查询

posted @ 2019-11-27 23:00  &#127838;面包&#127838;  阅读(88)  评论(0编辑  收藏  举报