首页 > 其他 > 详细

django之模型层

时间:2019-09-19 21:13:15      阅读:86      评论:0      收藏:0      [点我收藏+]
相关知识盘点:查看orm内部sql语句的方法
    1.看是否是queryset 对象,是的话,可直接.query查看SQL语句;
    2.在django配置文件中,配置相关参数,orm查询时自动打印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,
                },
            }
        }
        
案例相关:
    from django.db import models
    class Book(models.Model):
        title = models.CharField(max_length=255)
        price = models.DecimalField(max_digits=8,decimal_places=2)
        publish_date = models.DateField(auto_now_add=True)
        # 库存数
        kucun = models.IntegerField(null=True)
        # 卖出数
        maichu = models.IntegerField(null=True)
        publish = models.ForeignKey(to=Publish)  # 默认是跟publish的主键字段做的一对多外键关联
        authors = models.ManyToManyField(to=Author)
        # 虚拟字段      1.自动创建第三张表    2.帮助orm跨表查询

    class Publish(models.Model):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=32)
        # email = models.EmailField()  # 就是varchar(254)

    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to=AuthorDetail)

    class AuthorDetail(models.Model):
        phone = models.BigIntegerField()
        addr = models.CharField(max_length=64)
        
1.查询的方法:
    1.all(): 查询所有结果
    
    2.filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
    
    3.get(**kwargs): 返回数据对象,结果只有一个,没匹配到报错
    
    4.exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
      eg:
         print(models.Book.objects.exclude(pk=1))  #只要pk不是1的数据全部查询出来

    5.order_by(*field): 对查询结果排序;默认是升序,加-就是降序
      eg:
        print(models.Book.objects.order_by(price))   # 默认是升序
        print(models.Book.objects.order_by(-price))  # 加负号就是降序

    6.reverse(): 对查询结果反向排序 
      eg:
        print(models.Book.objects.order_by(price).reverse())
        
        注:前面要先有排序才能反向

    7.count(): 返回数据库中匹配查询(QuerySet)
      eg: 
        print(models.Book.objects.count()) #对查询出来的结果进行一个计数

    8.first(): 返回第一条记录 
    
    9.last(): 返回最后一条记录

    10.exists():存在返回True,否则返回False
      eg:
        print(models.Book.objects.filter(pk=1000).exists())

    11.values(*field): 返回一个ValueQuerySet对象,运行后得到的并不是一系列
      eg:
        print(models.Book.objects.values(title,price))  # 得到的结果是列表套字典

    12.values_list(*field): 它与values()类似
      eg:
        print(models.Book.objects.values_list(title,price))  # 得到的结果是列表套元组

    13.distinct(): 从返回结果中剔除重复纪录
      eg:
        print(models.Book.objects.values(title,price,create_time).distinct())
        
        注:去重的前提是 一定要有完全重复的数据 才能去重

2.双下滑查询:
    1.__gt: 大于
        eg:查询价格大于200的书籍
        res = models.Book.objects.filter(price__gt=200)
    2.__lt: 小于
        eg:查询价格小于200的书籍
        res = models.Book.objects.filter(price__lt=200)
    3.__gte:大于等于
        eg:查询价格大于等于200.22的书籍
        res = models.Book.objects.filter(price__gte=200.22)
    4.__lte:小于等于
        eg:查询价格小于等于200.22的书籍
        res = models.Book.objects.filter(price__lte=200.22)
    5.__in:或者
        eg:查询价格要么是200,要么是300,要么是666.66
        res = models.Book.objects.filter(price__in=[200,300,666.66])
    6.__range:区间 左右都包括
        eg:查询价格在200到800之间的
        res = models.Book.objects.filter(price__range=(200,800))
    7.__contains:模糊匹配
        eg:查询书籍名字中包含p的
        res = models.Book.objects.filter(title__contains=p)  # 仅仅只能拿小写p
        res = models.Book.objects.filter(title__icontains=p)  # 忽略大小写
    8.__startswith:以...开头
        eg:查询书籍是以三开头的
        res = models.Book.objects.filter(title__startswith=)
    9.__endswith:以...结尾
        eg:查询书籍是以三结尾的
        res = models.Book.objects.filter(title__endswith=)
    10.__year:查询年相关的
        eg:查询出版日期是2017的年(******)
        res = models.Book.objects.filter(create_time__year=2017)
            
    

3.多表查询:
    一对多的字段的增删改查:
        增:
            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()  # 默认都是级联更新 级联删除


    多对多字段的增删改查:
        增(add):既可以传数字也可以传对象并且支持一次性传多个,逗号隔开即可
            1.要给主键为1的书籍添加两个作者
                传数字:
                    book_obj = models.Book.objects.filter(pk=1).first()
                    book_obj.authors.add(1)
                    book_obj.authors.add(2,3)
                传对象:
                    author_obj = models.Author.objects.filter(pk=1).first()
                    author_obj1 = models.Author.objects.filter(pk=2).first()
                    author_obj2 = models.Author.objects.filter(pk=3).first()
                    book_obj.authors.add(author_obj)
                    book_obj.authors.add(author_obj1,author_obj2)
                
        改(set):
            1.将主键为1的书籍对象 作者修改为2,3
                传数字:
                    book_obj = models.Book.objects.filter(pk=1).first()
                    book_obj.authors.set([2,])
                    book_obj.authors.set([2,3])
                传对象:
                    author_obj = models.Author.objects.filter(pk=1).first()
                    author_obj1 = models.Author.objects.filter(pk=2).first()
                    author_obj2 = models.Author.objects.filter(pk=3).first()
                    book_obj.authors.set([author_obj,])
                    book_obj.authors.set([author_obj, author_obj1, author_obj2])
                
                注:1.set中要传可迭代对象,可迭代对象中 可以是多个数字组合也可以是多个对象组合;
                   2.数字与对象不要混着用!!!

        删(remove|clear):remove支持传数字,对象,并且可以传多个; clear不需要传任何参数
            传数字:
                book_obj = models.Book.objects.filter(pk=1).first()
                book_obj.authors.remove(3)
                book_obj.authors.remove(1,2)
            传对象:    
                author_obj = models.Author.objects.filter(pk=1).first()
                author_obj1 = models.Author.objects.filter(pk=2).first()
                author_obj2 = models.Author.objects.filter(pk=3).first()
                book_obj.authors.remove(author_obj)
                book_obj.authors.remove(author_obj1,author_obj2)
            什么都不传:将xx跟xx的关系全部清空
                book_obj = models.Book.objects.filter(pk=1).first()
                book_obj.authors.clear()  # 清空当前书籍与作者的所有关系
        
        注:    对象点击多对多虚拟字段 会直接跨到多对多的第三张表
                
4.跨表查询:
    正向与反向概念:
        1.一对一
            正向:author---关联字段在author表里--->authordetail        按字段
            反向:authordetail---关联字段在author表里--->author        按表名小写                          
        2.一对多
            正向:book---关联字段在book表里--->publish                 按字段
            反向:publish---关联字段在book表里--->book                 按表名小写_set.all() 因为一个出版社对应着多个图书            
        3.多对多
            正向:book---关联字段在book表里--->author                  按字段
            反向:author---关联字段在book表里--->book                  按表名小写_set.all() 因为一个作者对应着多个图书
        小结:(*****)
            正向查询按外键字段查,反向查询按表名小写
            
    子查询:将一张表的查询结果当做另外一个查询语句的条件
        1.查询书籍id是1 的出版社名称
            book_obj = models.Book.objects.filter(pk=1).first()
            print(book_obj.publish.name)
        
        2.查询书籍id是2 的作者姓名
            book_obj = models.Book.objects.filter(pk=2).first()
            print(book_obj.authors)  # app01.Author.None
            print(book_obj.authors.all())
            res = book_obj.authors.all()
            for r in res:
                print(r.name)
                
        3.查询作者是jason的家庭住址
            author_obj = models.Author.objects.filter(name=jason).first()
            print(author_obj.author_detail.addr)

        4.查询出版社是东方出版社出版的书籍
            publish_obj = models.Publish.objects.filter(name=东方出版社).first()
            # print(publish_obj.book_set)  # app01.Book.None
            print(publish_obj.book_set.all())

        5.查询作者是jason的写过的所有的书籍
            author_obj = models.Author.objects.filter(name=jason).first()
            print(author_obj.book_set)  # app01.Book.None
            print(author_obj.book_set.all())

        6.查询电话号码是130的作者姓名
            author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
            print(author_detail_obj.author.name)
            print(author_detail_obj.author.age)
                
        7.查询书籍id为1 的作者的电话号码
            book_obj = models.Book.objects.filter(pk=1).first()
            author_list = book_obj.authors.all()
            for author_obj in author_list:
                print(author_obj.author_detail.phone)
                    
        小结:
            当反向查询的结果有多个时,要在后面加上_set;
    
    连表操作(基于__):
        1.查询jason作者的手机号
            正向:    
                res = models.Author.objects.filter(name=jason).values(author_detail__phone,author_detail__addr)
                print(res)
            反向:
                res1 = models.AuthorDetail.objects.filter(author__name=jason).values(phone)
                print(res1)

        2.查询jason这个作者的年龄和手机号
            正向
                res = models.Author.objects.filter(name=jason).values(age,author_detail__phone)
                print(res)
            反向
                res1 = models.AuthorDetail.objects.filter(author__name=jason).values(phone,author__age)
                print(res1)

        3.查询手机号是130的作者年龄
            正向
                res = models.AuthorDetail.objects.filter(phone=130).values(author__age)
                print(res)
            反向:
                res1 = models.Author.objects.filter(author_detail__phone=130).values(age)
                print(res1)

        4.查询书籍id是1 的作者的电话号码
            res = models.Book.objects.filter(pk=1).values(authors__author_detail__phone)
            print(res)
        
        5.查询出版社为北方出版社的所有图书的名字和价格
            res = models.Publish.objects.filter(name=北方出版社).values(book__title,book__price)
            print(res)

        6.查询北方出版社出版的价格大于19的书
            res = models.Book.objects.filter(price__gt=19,publish__name=北方出版社).values(title,publish__name)
            print(res)

        注:只要表里面有外键字段,你就可以无限制跨多张表    
            eg:外键字段1__外键字段2...__外键字段__普通字段n
            
    聚合查询(aggregate):最大,最小,个数,平均,总和
        先导入 from django.db.models import Max,Min,Count,Avg,Sum...
            res = models.Book.objects.aggregate(Sum(price))
            res1 = models.Book.objects.aggregate(Avg(price))
            res2 = models.Book.objects.aggregate(Count(price))
            res3 = models.Book.objects.aggregate(Max(price))
            res4 = models.Book.objects.aggregate(Min(price))
            res5 = models.Book.objects.aggregate(Max(price),Min(price),Count(pk),Avg(price),Sum(price))
        
        注: aggregate(后面可跟多个函数)
        
        
    分组查询(annotate):models.那个表名就以那个分组
        from django.db.models import Max, Min, Count, Avg, Sum
        1.统计每一本书的作者个数
            res = models.Book.objects.annotate(author_num = Count(authors)).values(author_num,title)
            print(res)

        2.统计出每个出版社卖的最便宜的书的价格
            res = models.Publish.objects.annotate(mmp = Min(book__price)).values(name,mmp)
            print(res)

        3.统计不止一个作者的图书
            res = models.Book.objects.annotate(author_num=Count(authors)).filter(author_num__gt=1)
            print(res)
                    
        4.查询各个作者出的书的总价格
            res = models.Author.objects.annotate(sp=Sum(book__price)).values(name,sp)
            print(res)

    F查询:本质就是从数据库中获取某个字段的值
        from django.db.models import F
        1.查询卖出数量
            res = models.Book.objects.filter(kucun__gt=F(maichu))
            print(res)

        2.将书籍库存数全部增加1000
            models.Book.objects.update(kucun=F(kucun)+1000)

        3.把所有书名后面加上新款
            要先导入:
            from django.db.models.functions import Concat
            from django.db.models import Value

            ret3 = models.Book.objects.update(title=Concat(F(title), Value(新款)))
            models.Book.objects.update(title = F(title)+新款)  # 不能这么写
    
    Q查询:默认and,可人为改为 or , not
        from django.db.models import Q
        1.查询书籍名称是三国演义或者价格是444.44
          and:
            res = models.Book.objects.filter(title=三国演义,price=444.44)  # filter只支持and关系
            res1 = models.Book.objects.filter(Q(title=三国演义),Q(price=444))  # 如果用逗号 那么还是and关系
          
          or:
            res2 = models.Book.objects.filter(Q(title=三国演义)|Q(price=444))
          
          not:
            res3 = models.Book.objects.filter(~Q(title=三国演义)|Q(price=444))
    
    Q高级用法(了解):
        q = Q()
        q.connector = or  # 修改查询条件的关系   默认是and
        q.children.append((title__contains,三国演义))  # 往列表中添加筛选条件
        q.children.append((price__gt,444))  # 往列表中添加筛选条件
        res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
        print(res)

 

django之模型层

原文:https://www.cnblogs.com/wyf20190411-/p/11552247.html

(1)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!