django框架

今日内容:

模型层:就是rom 操作数据库的增删改查

 

ps:在django中 你可以写一个单独测试某一个py文件的测试脚本 不需要再频繁的走web请求,也可以在tests里面写
需要导入固定句式的模块:
1 import os
2 
3 
4 if __name__ == "__main__":
5     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings")
6     import django
7     django.setup()
8     """在下面就可以写针对某一个py文件的测试代码"""
9     from app01 import models
View Code

 

首先创建模型表出来:

 1 # 书籍表
 2 class Book(models.Model):
 3     title = models.CharField(max_length=255)
 4     price = models.DecimalField(max_digits=8, decimal_places=2)
 5     publish_date = models.DateField(auto_now_add=True)
 6     # 书籍表和出版社表建立一对多关系
 7     publish = models.ForeignKey(to='Publish')  # 默认是跟publish的主键字段做的一对多外键关联
 8     # 书籍表和作者表建立多对多关系
 9     authors = models.ManyToManyField(to='Author')
10 
11     # 虚拟字段      1.自动创建第三张表    2.帮助orm跨表查询
12     def __str__(self):
13         return self.title
14 
15 # 出版社表
16 class Publish(models.Model):
17     name = models.CharField(max_length=32)
18     addr = models.CharField(max_length=32)
19 
20 
21     def __str__(self):
22         return self.name
23 
24 # 作者表
25 class Author(models.Model):
26     name = models.CharField(max_length=32)
27     age = models.IntegerField()
28     # 作者表和作者详情表建立一对一关系
29     author_detail = models.OneToOneField(to='AuthorDetail')
30 
31     def __str__(self):
32         return self.name
33 
34 #作者详情表
35 class AuthorDetail(models.Model):
36     phone = models.BigIntegerField()
37     addr = models.CharField(max_length=64)
38     """
39     models.py中的模型类__str__方法 必须返回一个字符串形式数据!!!
40 
41     """
42 
43     def __str__(self):
44         return self.addr
View Code

 

补充:神奇的双下滑线查询

    神奇的双下划綫查询
        价格大于 小于 大于等于  小于等于   在什么之间  或好几个选择
        price__gt
        price__lt
        price__gte
        price__lte
        price__in
        price__range
        书籍名称中包含
            title__contains='p'
            title__icontains='p'
        创建的年份
            create_time__year

详细操作:

 1   """神奇的双下滑查询"""
 2     # 查询价格大于200的书籍
 3     # res = models.Book.objects.filter(price__gt=200)
 4     # print(res)
 5     # 查询价格小于200的书籍
 6     # res = models.Book.objects.filter(price__lt=200)
 7     # print(res)
 8 
 9     # 查询价格大于等于200.22的书籍
10     # res = models.Book.objects.filter(price__gte=200.22)
11     # print(res)
12     # 查询价格小于等于200.22的书籍
13     # res = models.Book.objects.filter(price__lte=200.22)
14     # print(res)
15 
16     # 查询价格要么是200,要么是300,要么是666.66
17     # res = models.Book.objects.filter(price__in=[200,300,666.66])
18     # print(res)
19     # 查询价格在200到800之间的
20     # res = models.Book.objects.filter(price__range=(200,800))  # 两边都包含
21     # print(res)
22 
23     # 查询书籍名字中包含p的
24     """原生sql语句 模糊匹配
25         like 
26             %
27             _
28     """
29     # res = models.Book.objects.filter(title__contains='p')  # 仅仅只能拿小写p
30     # res = models.Book.objects.filter(title__icontains='p')  # 忽略大小写
31     # print(res)
32 
33     # 查询书籍是以三开头的
34     # res = models.Book.objects.filter(title__startswith='三')
35     # res1 = models.Book.objects.filter(title__endswith='p')
36     # print(res)
37     # print(res1
38 
39     # 查询出版日期是2017的年(******)
40     res = models.Book.objects.filter(create_time__year='2017')
41     print(res)
View Code

 

1.一对多字段的增删改查:

    # 一对多字段的增删改查
    # 增 有俩个方法
    # 1.字段名 publish_id 直接传数字
    models.Book.objects.create(title='三国演义',price=199.99,publish_id=1)
    # 2.获取你要传入的出版社对象 然后 publish直接传出版社对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj)

    # 改 也是俩种方法
    # 1.字段名 publish_id 直接传数字
    models.Book.objects.filter(pk=1).update(publish_id=3)
    # 2.获取你要修改的出版社对象 然后 publish直接传要修改出版社对象
    publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.filter(pk=1).update(publish=publish_obj)

    # 删 # 默认是级联删除 级联更新
    models.Publish.objects.filter(pk=1).delete()

 

2.多对多字段的增删改查

 1 一共就4个方法:
 2  add()
 3     set()
 4     remove()
 5     上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象 
 6     clear()
 7     clear括号内不需要传任何参数
 8 
 9  # 增:
10     # 1. 要为主键为1的书籍添加2个作者  通过数字
11     book_obj = models.Book.objects.filter(pk=1).first()
12     # # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表
13     print(book_obj.authors) # app01.Author.None
14     book_obj.authors.add(1)
15     book_obj.authors.add(2,3)
16 
17     # 2.通过对象
18     author_obj = models.Author.objects.filter(pk=1).first()
19     author_obj1 = models.Author.objects.filter(pk=2).first()
20     author_obj2 = models.Author.objects.filter(pk=3).first()
21     book_obj = models.Book.objects.filter(pk=1).first()
22     book_obj.authors.add(author_obj)
23     book_obj.authors.add(author_obj1,author_obj2)
24     '''
25     注意:add()
26     是给书籍添加作者  括号内既可以传数字也可以传对象
27     并且支持一次性传多个  逗号隔开即可
28     '''
29 
30     #
31     # 1.传数字
32     # 将主键1的书籍对象 作者修改为2,3
33     book_obj = models.Book.objects.filter(pk=1).first()
34     book_obj.authors.set([2,])
35     book_obj.authors.set([2,3])
36 
37     # 2.传对象
38     author_obj = models.Author.objects.filter(pk=1).first()
39     author_obj1 = models.Author.objects.filter(pk=2).first()
40     author_obj2 = models.Author.objects.filter(pk=3).first()
41     book_obj = models.Book.objects.filter(pk=1).first()
42     book_obj.authors.set([author_obj,])
43     book_obj.authors.set([author_obj,author_obj1,author_obj2])
44     '''
45     注意:set()
46      set()括号内 需要传一个可迭代对象 
47     可迭代对象中 可以是多个数字组合
48     也可以是多个对象组合
49     但是不要混着用!!!
50     '''
51     #
52     # 1.传数字
53     book_obj = models.Book.objects.filter(pk=1).first()
54     book_obj.authors.remove(3)
55     book_obj.authors.remove(1,2)
56     # 2. 传对象
57     author_obj = models.Author.objects.filter(pk=1).first()
58     author_obj1 = models.Author.objects.filter(pk=2).first()
59     author_obj2 = models.Author.objects.filter(pk=3).first()
60     book_obj = models.Book.objects.filter(pk=1).first()
61     book_obj.authors.remove(author_obj)
62     book_obj.authors.remove(author_obj1,author_obj2)
63     '''
64     注意:
65     remove()括号内既可以传数字 也可以传对象 
66     并且支持传对个 逗号隔开即可
67     '''
68     # clear() 清空所有数据
69     book_obj = models.Book.objects.filter(pk=1).first()
70     book_obj.authors.clear() # 清空当前书籍与作者的所有关系
View Code

 

 

跨表查询(重点):相当于 子查询 

子查询:将一张表的查询结果当做另外一个查询语句的条件
跨表查询分为 正向查询和反向查询

正向与反向的概念:

 # 一对一
    # 正向:author---关联字段在author表里--->authordetail        按字段
    # 反向:authordetail---关联字段在author表里--->author        按表名小写
      
    # 一对多
    # 正向:book---关联字段在book表里--->publish        按字段
    # 反向:publish---关联字段在book表里--->book        按表名小写_set.all() 因为一个出版社对应着多个图书
    
    # 多对多
    # 正向:book---关联字段在book表里--->author        按字段
    # 反向:author---关联字段在book表里--->book        按表名小写_set.all() 因为一个作者对应着多个图书


说简单点就是:
基于找的这一方有外键字段就是正向,没有就是反向

正向查询按外键字段
反向查询按表名小写
    
重点:
当你正向查询的时候,查询的结果是多个,那么就需要 点all()

当你反向查询的结果是多个的时候 就需要加_set 在点all()
否则直接表明小写即可

 
View Code

 

 

基于双下滑线的跨表查询:相当于连表操作

left join
inner join
right join
union
 1   # 1.查询zy作者的手机号
 2     # 正向
 3     res = models.Author.objects.filter(name='zy').values('author_detail__phone')
 4     print(res)
 5     # 反向   因为是反向查询,筛选条件用表名小写,然后双下滑线等于名字,再拿到这个人的手机号
 6     res1 = models.AuthorDetail.objects.filter(author__name='zy').values('phone')
 7     print(res1)
 8 
 9     # 2.查询zy这个作者的家庭住址和手机号
10     # 正向
11     res = models.Author.objects.filter(name='zy').values('author_detail__addr','author_detail__phone')
12     print(res)
13     # 反向
14     res1 = models.AuthorDetail.objects.filter(author__name='zy').values('addr','phone')
15     print(res1)
16 
17     # 3.查询
18     # 查询手机号是130的作者家庭住址
19     # 正向
20     res = models.AuthorDetail.objects.filter(phone=130).values('author__addr')
21     print(res)
22     # # 反向
23     res1 = models.Author.objects.filter(author_detail__phone=130).values('addr')
24     print(res1)
25 
26     # 4.查询书籍id是1 的作者的电话号码               外键字段一 外键字段二  普通字段
27     res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
28     print(res) # 只要表里面有外键字段 你就可以无限制跨多张表
29 
30     # 1.查询出版社为北方出版社的所有图书的名字和价格
31     res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
32     print(res)
33 
34     # 2.查询北方出版社出版的价格大于19的书
35     res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
36     print(res)
View Code

 

 聚合函数:

  # 聚合函数:关键字参数(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'))
    print(res5)
    print(res)
    print(res1)
    print(res2)

 

分组查询:

 # 分组查询跟数据库的分组是一样的,只不过django里面用的是:annotate
    # 分组跟聚合函数配合使用
    """
     只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
    最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选
     """
    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('mmp','name')
    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查询:

    # F查询的本质就是从数据库中获取某个字段的值
    '''
    之前查询等号后面的条件都是我们人为输入的,
    现在变成了需要从数据库中获取数据放在等号后面
    '''
    # 使用之前需要先导入模块
    from django.db.models import F
    # 1.查询库存数大于卖出数的书籍
    res = models.Book.objects.filter(kucun__gt=F('maichu'))
    print(res)

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

    # 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查询:

 from django.db.models import Q
    # 查询书籍名称是三国演义或者价格是444.44的书
    res = models.Book.objects.filter(title='三国演义',price=444.44)  # filter只支持and关系
    res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444))  # 如果用逗号 那么还是and关系
    res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) #or
    res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) #not  
    print(res2)

 

Q高级查询:

  # 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)

 

posted @ 2019-09-19 22:40  ZHANGYUZY  阅读(124)  评论(0编辑  收藏  举报