您好,欢迎来到好兔宠物网。
搜索
您的当前位置:首页django之模型层

django之模型层

来源:好兔宠物网
相关知识盘点:查看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(2)

    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=)
        
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=1.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)

 

转载于:https://www.cnblogs.com/wyf20190411-/p/11552247.html

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- howto1234.com 版权所有 湘ICP备2023017662号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务