DJango周总结二:模型层,单表,多表操作,连表操作,数据库操作,事务

mac2022-06-30  28

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中跟数据库相关的代码 就必须重新执行上面的两条命令 缺一不可(******)

转载于:https://www.cnblogs.com/Fzhiyuan/p/11564510.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)