zoukankan      html  css  js  c++  java
  • DJango周总结二:模型层,单表,多表操作,连表操作,数据库操作,事务

    django周复习二
     1,模型层:
      1单表操作:
       13个必会操作总结
        返回QuerySet对象的方法有
        all()
        filter()
        exclude()
        order_by()
        reverse()
        distinct()
        特殊的QuerySet
        values()       返回一个可迭代的字典序列
        values_list() 返回一个可迭代的元祖序列
        返回具体对象的
        get()
        first()
        last()
        返回布尔值的方法有:
        exists()
        返回数字的方法有
        count()
          增
       # 方式1: create
       # book_obj  = models.Book.objects.create(title='三国',price=19.99,create_time='2019-11-11')
       # print(book_obj.title)
       # 方式2:对象点save()方法   效率极低,因为每执行一次,相当于从数据库从头到尾执行一遍
       # from datetime import datetime
       # ctime = datetime.now()
       # book_obj = models.Book(title='西游记',price=96.66,create_time=ctime)
       # book_obj.save()
       查
       # print(models.Book.objects.all())
       # print(models.Book.objects.get(id=1))
       # print(models.Book.objects.get(pk=1))
       """
       pk会自动查找到当前数据的主键字段
       """
       # print(models.Book.objects.filter(pk=2))
       改
       # 1.update
       # models.Book.objects.filter(pk=1).update(title='三国演义')
       # 2.对象.save()
       # book_obj = models.Book.objects.get(pk=1)
       # book_obj.price = 666.66
       # book_obj.save()
       删除  delete()
       # models.Book.objects.filter(pk=2).delete()
       # < 1 > all(): 查询所有结果
       # < 2 > filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
       # < 3 > get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
       # < 4 > exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
       # print(models.Book.objects.exclude(pk=1))  # 只要pk不是1的数据全部查询出来

       # < 5 > order_by(*field): 对查询结果排序('-id') / ('price')
       # print(models.Book.objects.order_by('price'))  # 默认是升序
       # print(models.Book.objects.order_by('-price'))  # 加负号就是降序

       # < 6 > reverse(): 对查询结果反向排序 >> > 前面要先有排序才能反向
       # print(models.Book.objects.order_by('price').reverse())
       # < 7 > count(): 返回数据库中匹配查询(QuerySet)
       # print(models.Book.objects.count())  # 对查询出来的结果进行一个计数

       # 的对象数量。
       # < 8 > first(): 返回第一条记录
       # print(models.Book.objects.filter(pk=1).first())
       # < 9 > last(): 返回最后一条记录
       # print(models.Book.objects.all())
       # print(models.Book.objects.all().last())
       # < 10 > exists(): 如果QuerySet包含数据,就返回True,否则返回False
       # print(models.Book.objects.filter(pk=1000))
       # print(models.Book.objects.filter(pk=1000).exists())

       # < 11 > values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
       # model的实例化对象,而是一个可迭代的字典序列
       # print(models.Book.objects.values('title','price'))  # 得到的结果是列表套字典
     
       # < 12 > values_list(*field): 它与values()
       # print(models.Book.objects.values_list('title','price'))  # 得到的结果是列表套元组

       # 非常相似,它返回的是一个元组序列,values返回的是一个字典序列
       # < 13 > distinct(): 从返回结果中剔除重复纪录
       """
       去重的前提是 一定要有完全重复的数据 才能去重
       """
       # print(models.Book.objects.filter(title='三国演义').distinct())
       # print(models.Book.objects.values('title','price','create_time').distinct())
       
       
      2,神奇的双下划线查询
        字段__
        __gt   大于
        __lt   小于
        __gte  大于等于
        __lte  小于等于
        __in[]   在不在里面
        __range() 在不在某范围,两边都包含
        __contains='p'   判断是否含有p  只能判断小写
        __icontains='p'  判断是否含有p  忽略大小写
        __startswith='三'  判断是否以三开头
        __endswith='p'     判断是否以p结尾
        __year='2017'     查看2017年的
        
        models.Book.objects.filter(price__gte=200)   大于等于
        models.Book.objects.filter(price__lte=200)  小于等于
        models.Book.objects.filter(price__in=[200,300,666.66])  查询价格要么是200,要么是300,要么是666.66
        models.Book.objects.filter(price__range=(200,800))  # 两边都包含  查询价格在200到800之间的
        models.Book.objects.filter(title__contains='p')  # 仅仅只能拿小写p  查询书籍名字中包含p的
        models.Book.objects.filter(title__icontains='p')  # 忽略大小写
        models.Book.objects.filter(title__startswith='三')          查询书籍是以三开头的
        models.Book.objects.filter(title__endswith='p')
        
        models.Book.objects.filter(create_time__year='2017')    查询出版日期是2017的年(******)
        
      3,多表操作
       一对多:ForeignKey
       一对一:OnoToOneField  可以用ForeignKey代替ForeignKey(unique=True)
        上面两个关键字所创建出来的字段会自动加上_id后缀
       
       多对多:ManyToManyFiled
       该字段并不会真正的在表中展示出来 它仅仅是一个虚拟字段
        1.告诉orm自动创建第三张表
        2.帮助orm跨表查询
        
       
       2.一对多增删改查:
          publish_id传数字                                                          
          models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)     
        publish直接传出版社对象                                                       
          publish_obj = models.Publish.objects.filter(pk=2).first()              
          models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj)
                           
          改                                                                      
          传数字的                                                                   
          models.Book.objects.filter(pk=1).update(publish_id=3)                  
          传对象的                                                                   
          publish_obj = models.Publish.objects.filter(pk=2).first()              
          models.Book.objects.filter(pk=1).update(publish=publish_obj)           
                           
          删                                                                      
          models.Publish.objects.filter(pk=2).delete()  # 默认都是级联更新 级联删除          
        
       3,多对多字段的增删改查
         add()       增    传数字,对象
         set()        改   传数字,对象  ,必须是可迭代对象
         remove()     删    传数字,对象
            以上可以传多个
         clear()      删所有   括号内不要传参数
       
         # 增
          add()
          1,add括号中传数字
          
          
              # 主键为6的书籍增加一个作者
            book_obj = models.Book.objects.filter(pk=6).first()
            print(book_obj.authors) 此时为None,就是跳到了第三张表
            
            #对象点击多对多虚拟字段时,会直接多对多的第三张表
            #此时book_obj.authors就是直接跨到第三张表
            book_obj.authors.add(1)  # 此时就是给id为6的书籍添加一个作者
            book_obj.authors.add(2,3)
            # add括号中既可以传一个数字,又可以传多个数字
            # 括号中一个数字,此时就是给id为6的书籍添加一个作者,
            # 所以括号中有几个数字,就是添加几个作者,数字表示的是作者的id号
          
          2,add括号中传对象
            增加一条
                book_obj = models.Book.objects.filter(pk=4).first()
             aut_obj = models.Author.objects.filter(pk=3).first()
             book_obj.authors.add(aut_obj)
            
            增加多条
            
             book_obj = models.Book.objects.filter(pk=5).first()
             book_obj1= models.Book.objects.filter(pk=5).first()
             
             aut_obj = models.Author.objects.filter(pk=2).first()
             aut_obj1= models.Author.objects.filter(pk=1).first()
             aut_obj2 = models.Author.objects.filter(pk=9).first()
             
             book_obj.authors.add(aut_obj,aut_obj1,aut_obj2)
             book_obj1.authors.add(aut_obj1)
            总结:
            add是给书籍添加作者 括号内既可以传数字也可以传作者对象
            并且支持一次性传多个 逗号隔开就可以
            注意 :对象点虚拟字段就是跳到了第三张表
            
            
         改:
          将主键为5的书籍对象 作者修改为2,3
          set()
           括号中以列表的形式,是可迭代对象才可以传一个参数也要以列表的形式
           1,传数字,
           
               book_obj = models.Book.objects.filter(pk=5).first()
            book_obj.authors.set([5,])   传一个参数
            book_obj.authors.set([2,3])  传多个参数
             本质就是修改,有点类似于删除,把不要的删除,把要的留下来
          
           2,传作者对象
           
             aut_obj = models.Author.objects.filter(pk=2).first()
             aut_obj1= models.Author.objects.filter(pk=1).first()
             aut_obj2 = models.Author.objects.filter(pk=9).first()
             
             book_obj.authors.set([aut_obj,aut_obj1,aut_obj2])
       
          总结:
           set()括号内 需要传一个可迭代对象
           可迭代对象  可以是多个数字组合
           也可以是多个对象组合
           但是不能混在一起使用,即不能既有数字,又有对象!!!
           要么纯数字,要么纯对象
           
           
           
         删:
          remove()
           1,传数字
           
              book_obj = models.Book.objects.filter(pk=5).first()
      
           book_obj.authors.remove(3)
           
           2,传对象
           
            aut_obj = models.Author.objects.filter(pk=2).first()
            aut_obj1= models.Author.objects.filter(pk=1).first()
            aut_obj2 = models.Author.objects.filter(pk=9).first()
            
            book_obj.authors.remove(aut_obj)
            book_obj.authors.remove(aut_obj,aut_obj1,aut_obj2)
          总结:
           remove()括号内既可以传数字 也可以传对象
           并且支持传多个,逗号隔开即可
           
           将某本书和作者的关系全部清空,用clear()
           即清空当前这个作者与书籍的关系
           
           book_obj = models.Book.objects.filter(pk=5).first()
           book_obj.authors.clear()
           
           
        跨表查询:
                正向与反向的概念
       
           # 一对一
           # 正向:author---关联字段在author表里--->authordetail  按字段
           # 反向:authordetail---关联字段在author表里--->author  按表名小写
           
            
           # 一对多
           # 正向:book---关联字段在book表里--->publish  按字段
           # 反向:publish---关联字段在book表里--->book  按表名小写_set.all() 因为一个出版社对应着多个图书
           
           # 多对多
           # 正向:book---关联字段在book表里--->author  按字段
           # 反向:author---关联字段在book表里--->book  按表名小写_set.all() 因为一个作者对应着多个图书
           
           
           正向查询按外键字段
           反向查询按表名小写
           
           基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)
           
           强调:在书写orm语句的时候 跟写sql语句一样
           不要尝试着 一次性写完  应该做到写一点看一点再一点
       1,如果外键字段在你当前这张表中,那么如果由你当前这张表向另一张表查询就是正向
        关系字段在你当前这张表,由你这张表去查,正向
        关系字段不在你当前这张表,由你这张表去查,反向
        
        正向查询按外键字段
        反向查询按表名小写
        
        
        # 基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)
         #查询书籍为4的出版社名称
         book_obj = models.Book.objects.filter(pk=4).first()
         print(book_obj.publish.name)
         print(book_obj.publish.addr)
         # 查询书籍id是5的作者姓名
         book_obj = models.Book.objects.filter(pk=5).first()
         
         print(book_obj.authors)   # app01.Author.None
         #书籍有多个作者,所以拿到为None
         print(book_obj.authors.all()) 拿到的是对象,
         
         当你外键字段对应的值有多个的时候就用all(),为一个的时候就不用all()
           
            # 查询作者是jason的家庭住址
          auth_obj = models.Author.objects.filter(name='jason').first()
          print(auth_obj.author_detail.addr)
         
          
         反向查询:
              # 查询出版社是东方出版社出版的书籍
           publish_obj = models.Publish.objects.filter(name='东方出版社').first()
           print(publish_obj.book_set.all())
           # 查询作者是jason写过的所有书籍
           # auth_obj = models.Author.objects.filter(name='jason').first()
           # print(auth_obj.book_set)
           # print(auth_obj.book_set.all())
           
           # 查询作者号码是120的作者姓名
           auth_obj = models.AuthorDetail.objects.filter(phone=120).first()
           print(auth_obj.author.name)
           print(auth_obj.author.age)
           
         总结:
          反向查询,当你反向查询的结果是多个的时候就需要加 _set
                  当你反向查询的结果是一个时就不需要加_set
            即表名小写即可
           跨表查询:可以连续的查询
        # 基于双下划綫的跨表查询(连表查询)
         models.Book.objects.filter().values('publish__name')
         models.Publish.objects.filter(book__title='三').values('name')
         
         models.Book.objects.filter().values('authors__author_detail__phone')
         # 只要表中有外键字段 你可以通过__无限制的跨表 
        
       F与Q
        F查询
        从数据库中获取字段对应的数据
        库存数大于卖出数
       
        Q查询
         与
          filter(Q(),Q())
          filter(Q()&Q())
         或
          filter(Q()|Q())
         非
          filter(~Q())
          
         补充
          q = Q()
          q.connector = 'or'
          q.children.append(('title','三'))
          q.children.append(('price',666))
          models.Book.objects.filter(q)
        
     2,常见字段  
       AutoField()    int primary key auto_increment
       CharField()    varchar()
       IntegerField()   int()
       big....   
       EmailField() varchar(254)
       DateField()      date
       DateTimeField()  datetime
        auto_now:每次修改数据都会更新时间
        auto_now_add:只在第一次创建数据的时候才会更新一次
        
        BooleanField(Field)
         is_delete = BooleanField()
         给该字段传值的时候 你只需要传布尔值即可
         但是对应到数据库  它存的是0和1
        TextField(Field)
         - 文本类型
         用来存大段文本
        
        FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
         upload_to = ""      用户上传的文件会自动放到等号后面指定的文件路径中
         storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
       
       自定义char字段
     
        class MyChar(models.Field):
         def __init__(self,max_length,*args,**kwargs):
          self.max_length = max_length
          super().__init__(max_length=max_length,*args,**kwargs)
         def db_type(self, connection):
          return 'char(%s)'%self.max_length
       外键字段
        当你在使用django2.X版本的时候 在建立外键关系时(*****)
        需要你手动添加几个关键点参数
         models.cascade
         db_constraints
     3,数据库查询优化
      only与defer
       
      select_releated与prefect_releated
      
      """数据库查询优化"""
       # orm内所有的语句操作 都是惰性查询:只会在你真正需要数据的时候才会走数据库,如果你单单只写orm语句时不会走数据库的
       # 这样设计的好处 在于 减轻数据库的压力 
      # res = models.Book.objects.only('title')
      # # print(res)
      # for r in res:
      #     # print(r.title)  # 只走一次数据库查询
      #     print(r.price)  # 当你点击一个不是only括号内指定的字段的时候 不会报错 而是会频繁的走数据库查询
      # res1 = models.Book.objects.defer('title')  # defer与only是相反的
      # for r in res1:  # defer会将不是括号内的所有的字段信息 全部查询出来封装对象中
      #     # 一旦你点击了括号内的字段  那么会频繁的走数据库查询
      #     print(r.price)
        # select_related与prefetch_related
      # select_related帮你直接连表操作 查询数据   括号内只能放外键字段
      # res = models.Book.objects.all().select_related('publish')
      # for r in res:
      #     print(r.publish.name)
      # res = models.Book.objects.all().select_related('publish__xxx__yyy__ttt')
      # print(res)
      # res = models.Book.objects.all()
      """
      select_related:会将括号内外键字段所关联的那张表  直接全部拿过来(可以一次性拿多张表)跟当前表拼接操作
      从而降低你跨表查询 数据库的压力
      
      注意select_related括号只能放外键字段(一对一和一对多)
       res = models.Book.objects.all().select_related('外键字段1__外键字段2__外键字段3__外键字段4')
      """
      # prefetch_related  不主动连表
      res = models.Book.objects.prefetch_related('publish')
      """
      不主动连表操作(但是内部给你的感觉像是连表操作了)  而是将book表中的publish全部拿出来  在取publish表中将id对应的所有的数据取出
      res = models.Book.objects.prefetch_related('publish')
      括号内有几个外键字段 就会走几次数据库查询操作   
      """
      for r in res:
       print(r.publish.name)
     4,事务
      
      ACID
       原子性
       一致性
       隔离性
       持久性
      from django.db import transaction
      with transaction.atomic():
       """数据库操作
       在该代码块中书写的操作 同属于一个事务
       """
       models.Book.objects.create()
       models.Publish.objects.create()
       # 添加书籍和出版社 就是同一个事务 要么一起成功要么一起失败
      print('出了 代码块 事务就结束')

     5,数据库连接:
      1,在settings.py 文件中进行更改,添加
       DATABASES = {
        'default': {
         'ENGINE': 'django.db.backends.mysql',
         'NAME': 'day56',
         'HOST':'127.0.0.1',
         'USER':'root',
         'PORT':3306,
         'PASSWORD':'123',
         'CHARSET':'utf8'
        }
       }
      2.在应用或者项目文件夹下的__init__文件中添加:
       import pymysql
       pymysql.install_as_MySQLdb()
       
      3,orm对象关系映射
       表        类
       一条条记录   对象
       记录中的字段  对象.属性
       
       
       首先需要在应用下的models.py中书写模型类
        class User(models.Model):
         # 将id字段设置为User表主键字段  在django orm中 你可以不写主键字典  django会默认给你的表创建一个名为id的主键字段
         # id = models.AutoField(primary_key=True)  # 一旦你自己指定了主键字段 那么django就不会自动再帮你创建了
         username = models.CharField(max_length=32)  # username varchar(32)   CharField必须要指定max_length参数
         password = models.IntegerField()  # password int
         
       *************************需要执行数据库迁移(同步)命令******************************
       python3 manage.py makemigrations  # 仅仅是在小本本上(migrations文件夹)记录数据库的修改 并不会直接操作数据
       python3 manage.py migrate  # 将数据库修改记录 真正同步到数据库
       注意:只要动了models中跟数据库相关的代码 就必须重新执行上面的两条命令 缺一不可(******)
  • 相关阅读:
    压缩打包linux 文件压缩解压命令Strut2教程java教程
    【leetcode】Valid Parentheses
    指向数据个人对指针的理解,欢迎大家批评Strut2教程java教程
    UML中的用例图
    Extjs4中组件的查找方式
    Extjs中选择组件、选择元素的方法
    [转载]C 内存管理详解
    C开发机顶盒实战代码之队列
    C机顶盒开发实战常用初始化类型:数组、结构、指针
    [转载]C语言链表的建立、插入和删除
  • 原文地址:https://www.cnblogs.com/Fzhiyuan/p/11564510.html
Copyright © 2011-2022 走看看