Django模板系统模型层

单表操作
    DateField里面的参数:
        auto_now:每次更新的时候,都会重新记录时间 (=True)
        auto_now_add:创建数据时,自动将当前时间记录下来 =(True)
 
    测试test创建
import os
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm.settings")
    import django
    django.setup()
    from app01 import models
##前三行去manage.py中复制
##特别需要注意的是  后面三句的顺序一定要写在__main__中,而且模型层导入放在最后,然后就可以开始测试了
 

 
    单表操作:(强调:只要是queryset对象就可以无限制的点queryset的方法)
models.Book.objects.filter().filter.filter.filter.filter.filter
    单表操作实战-增删改查
#新增数据
#方法1
obj=models.Book.objects.create(name='三国演义',price='10',publish='北方出版社',author='linxiao')
#方法2
obj1=models.Book(name='红楼梦',price='20',publish='南方出版社',author='lindaxian')
obj1.save()
 
#查询
#方法1
book_obj=models.Book.objects.all()
book_obj1=models.Book.objects.filter(name='三国演义',price='10').first()
#取到的是queryset对象 filter中的,是and的关系,.first获得的是一个Book的对象
#方法2
book_obj2=models.Book.objects.get(name='三国演义1')
#获得的直接是对象 但是数据不存在直接报错
 
#修改
#方法1
models.Book.objects.filter(price='20').update(price='15')
#方法2
book_obj=models.Book.objects.filter(name='三国演义').first()
book_obj.name='西游记'
book_obj.save()
#直接使用queryset.xxx可以直接修改保存  如果获得的是一个对象 然后对象.属性修改 必须使用save()保存
 
#删除
models.Book.objects.filter(name='西游记').delete()
#删除的值不存在 不会报错
  
    单表操作实战-补充
<1> all():                  查询所有结果
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象
<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(源码就去搂一眼~诠释为何只能是一个对象)
<4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
<5> order_by(*field):       对查询结果排序('-id')/('price')
<6> reverse():              对查询结果反向排序      >>>前面要先有排序才能反向
<7> count():                返回数据库中匹配查询(QuerySet)的对象数量。
<8> first():                返回第一条记录
<9> last():                 返回最后一条记录
<10> exists():              对查询出来的QuerySet进行有无数据的判断,有就返回True,否则返回False
<11> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列                             model的实例化对象,而是一个可迭代的字典序列
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<13> distinct():            从返回结果中剔除重复纪录
  
    单表操作实战-补充-双下划线的用法
#双下划线的用法
#查询价格大于30的数据
res=models.Book.objects.filter(price__gt='30')
 
#查询价格小于30的数据
res = models.Book.objects.filter(price__lt='30')
 
#查询价格大于等于30的数据
res = models.Book.objects.filter(price__gte='30')
 
#查询价格是否在列表中
res=models.Book.objects.filter(price__in=['20','10'])
 
#查询价格在某个区间范围内
res=models.Book.objects.filter(price__range=('0','50’))
 
#查询名称中含有’三’的书籍
title__contains=‘三’
 
#查询书籍名称中有字母p的书籍,并忽略大小写
title__icontains=‘p’
 
 
  
返回QuerySet对象的方法有:
    all()
    filter()
    exclude()
    order_by()
    reverse()
    distinct()
特殊的QuerySet
    values()       返回一个可迭代的字典序列
    values_list() 返回一个可迭代的元祖序列
          
返回具体对象的
    get()
    first()
    last()
 
多表操作
    如何判断表关系:一方能否有多个另一方,另一方能否有多个一方
    一对一:其实就是一张表被人为拆分成了两张表而已,主要是为了缓解查询压力
    一对多:通常建立在多的那一方
    多对多:多对多字段建立在哪张表都可以,但是通常建立在查询频率比较高的那张表里,为了后期的正向查询提高方便
 
多表关系的建立
#建立外键
publish=models.ForeignKey(to='Publish')
#建立多对多表 虚拟字段,只是告诉orm新建第三表表示book跟author多对多的关系
authors=models.ManyToManyField(to='Author’)
#一对一表
authordetail=models.OneToOneField(to='AuthorDetail')
 
    多表操作实战-一对多增删改查
#书籍表一对多字段的增删改查
#创建图书的两种方式
#publish_id直接传入出版社的id即可
models.Book.objects.create(name='金不梅',price=10,publish_id=1)
#publish直接传入出版社对象
publish_obj=models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(name='封神榜',price=100,publish=publish_obj)
 
#修改图书的两种方式
#方法一
models.Book.objects.filter(name='三国演义').update(publish_id=2)
#方法二
publish_obj=models.Publish.objects.filter(pk=2).first()
models.Book.objects.filter(name='金不梅').update(publish=publish_obj)
 
    多表操作实战-多对多增删改查
多对多字段数据的增删改查
    多对多字段新增 add()里面可以直接传id值,并且可以传多个,也可以传对象,也支持多个
    remove()删除
    clear()清空该图书的所有数据 不支持传参
    set()先清空 再添加 参数必须是可迭代对象
 
    多表操作实战-多对多增删改查代码
#数据多对多字段的增删改查
#给书籍对象添加作者
book_obj=models.Book.objects.filter(name='金不梅').first()
book_obj.authors.add(1) #给当前数据对象添加id为1的作者
book_obj.authors.add(1,2) #给当前对象添加id为1,2的作者
 
 
author_obj=models.Author.objects.filter(id=3).first()
author_obj2=models.Author.objects.filter(id=2).first()
author_obj3=models.Author.objects.filter(id=1).first()
author_queryset=models.Author.objects.all()
book_obj.authors.add(author_obj) #给当前数据对象添加作者
book_obj.authors.add(*author_queryset) #给当前数据对象添加作所有者
book_obj.authors.add(author_obj,author_obj2) #给当前数据对象添加作者1,2
 
#删除数对象与作者的绑定关系
book_obj=models.Book.objects.filter(pk=5).first()
book_obj.authors.remove(1,2) #支持传多个id 也支持传多个对象参数
 
#修改数据与作者的绑定关系
book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.set([1,]) #先清空再添加 参数必须是一个可迭代的对象 既可以传id值也可以传对象
 
#一次性清空作者的绑定关系
book_obj = models.Book.objects.filter(pk=5).first()
book_obj.authors.clear() #不支持传参,调用就意味清空所有
 
    
    跨表查询:
        正向查询按字段 反向查询按表名小写
        只要是查询结果是多的  要加个all()
 
 
    补充知识点
补充一个知识点概念
   正向查询按字段,反向查询按表名小写
      正向与反向
         # 一对一
         # 正向:author---关联字段在author表里--->authordetail          按字段
         # 反向:authordetail---关联字段在author表里--->author          按表名小写
         # 一对多
         # 正向:book---关联字段在book表里--->publish      按字段
         # 反向:publish---关联字段在book表里--->book      按表名小写
         # 多对多
         # 正向:book---关联字段在book表里--->author          按字段
         # 反向:author---关联字段在book表里--->book          按表名小写
       
         反向:
         一对多 反向后面要加_set.all() 查出来是queryset本身
         一对一不用加_set 查出来是对象本身
         多对多 反向后面要加_set.all() 查出来是queryset本身
    基于对象的跨表查询
#正向查询
#查询书籍是金不梅的出版社的地址
book_obj=models.Book.objects.filter(name='金不梅').first()
res=book_obj.publish.addr #一本书只能有一个出版社
 
#查询书籍金不梅的作者名字
book_obj=models.Book.objects.filter(name='金不梅').first()
res=book_obj.authors.all() #一本书可能有多个作者 要.all()
 
#反向查询
#查询东方出版社出版的书籍
#一对多 正向按字段 反向按表名小写加_set
publish_obj=models.Publish.objects.filter(name='东方出版社').first()
res=publish_obj.book_set.all() #只要不是一对一 都要.all()
 
#多对多
#查询所有林霄写过的书
author_obj=models.Author.objects.filter(name='林霄').first()
res=author_obj.book_set.all()
 
#一对一
#作者电话是110的作者的姓名
author_detail=models.AuthorDetail.objects.filter(phone='110').first()
res=author_detail.author.name
 
 
    基于双下划线的多表查询
#作者姓名是林霄写过书的价格 反向
res=models.Author.objects.filter(name='林霄').values('book__price')
 
#查询书籍id为1的出版社的addr 正向的
res=models.Book.objects.filter(id=1).values('publish__addr')  # 这里的publish不是表名小写而是字段
 
#查询书籍是金不梅的作者的电话号码
res=models.Book.objects.filter(name='金不梅').values('authors__authordetail__phone').first()
 
 
#  查询林霄作者的手机号
# 正向
res=models.Author.objects.filter(name='林霄').values('authordetail__phone')
 
# 反向
res=models.AuthorDetail.objects.filter(author__name='林霄').values('phone')
 
# 查询东方出版社出版的价格大于30的书
res=models.Publish.objects.filter(name='东方出版社',book__price__gt='30').values('book__name')
 
在控制台打印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.models import Avg,Sum,Max,Min,Count
res=models.Book.objects.all().aggregate(Avg('price'))
res=models.Book.objects.all().aggregate(Sum('price'))
res=models.Book.objects.all().aggregate(Max('price'))
res=models.Book.objects.all().aggregate(Min('price'))
res=models.Book.objects.all().aggregate(Count('price'))
分组查询
#给数据库设置严格模式 会报错
from django.db.models import Count,Min
# 统计出每个出版社买的最便宜的书的价格
publisher_list = models.Publish.objects.annotate(min_price=Min("book__price"))
 
 
F与Q查询
    F查询
        查询的条件左右两边都来自数据库 而非手动输入
#F查询 查询的条件左右两边都来自于数据库而非你自己定义的值
from django.db.models import Q,F
res=models.Book.objects.filter(maichu__gt=F('kuchu')).values('name')
#讲商品的价格全部提高50
models.Book.objects.update(price=F('price')+50)
    Q查询
        将filter内部默认的and关系转换成与或非
        与 &
        或 |
        非 ~
#Q查询能够将filter内部默认的and关系转化成或与非 或& 与| 非~
from django.db.models import Q
res=models.Book.objects.filter(Q(name='三国演义')|Q(name='水浒传')).values('name')
    Q的另一种用法
q=Q()
q.children.append(’name’,'金不梅’)
models.Book.objects.filter(q)
posted @ 2019-04-18 15:58  爱迷路的小怪兽  阅读(159)  评论(0编辑  收藏  举报