随笔 - 149,  文章 - 0,  评论 - 0,  阅读 - 12191

【单表操作】

用mysql数据库的时候,别忘在__init__里写这两行代码
import pymysql

pymysql.install_as_MySQLdb()

(测试脚本代码环境)

 

复制代码
 1 单独测试django某个功能层
 2     默认不允许单独测试某个py文件,必须先建路由对应关系,然后在视图函数里面才能执行ORM语句
 3     如果想要测试某个单独的ORM语句怎么办?
 4 --------------------------------
 5     测试环境1:pycharm提供的python console
 6 但有个不好,代码写完没法保存!!
 7 ----------
 8     测试环境2:自己搭建(自带的test或者自己创建)
 9     1.拷贝manage.py前四行
10     2.自己再加两行
11     import django
12     django.setup()
复制代码

 

(单表操作的增删改查)

复制代码
 1 模型表:
 2 
 3 class User(models.Model):
 4     name = models.CharField(max_length=32)
 5     age = models.IntegerField()
 6     # register_time= models.DateTimeFiel d(auto_now_add=True)
 7     register_time = models.DateField()  # 年月日
 8     # register_time=models.DateTimeField(auto_now_add=True)
 9     '''
10     DateField:年月日
11     DateTimeField:时分秒
12         有两个非常重要的参数
13         auto_now:每次操作数据的时候,该字段会自动将当前时间更新
14         auto_now_add:在创建数据的时候,会自动将当前创建时间记录下来,之后只要不人为的修改,那么就不会发生改变
15     '''
16 
17     # # 辨别last()方法
18     def __str__(self):
19         return '对象:%s' % self.name
20 
21 ---------------
22 测试脚本py文件
23 
24 import os
25 
26 if __name__ == '__main__':
27     os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject5day0064.settings')
28     import django
29 
30     django.setup()
31     from app01 import models
32 
33     # 增--方式一
34     models.User.objects.create(name='jason', age=18, register_time='2022-12-12')
35     # 日期格式
36     import datetime
37 
38     # 方式二:
39     ctime = datetime.datetime.now()
40     user_obj = models.User(name='egon', age=20, register_time=ctime)
41     user_obj.save()
42 
43 
44     #
45     res = models.User.objects.filter(name='egon').delete()
46     # 删--根据pk删
47     res = models.User.objects.filter(pk=2).delete()
48     print(res)  # 所删除影响的行数 (1, {'app01.User': 1})
49     '''
50     pk:会自动查找到当前表的主键字段,指代的就是当前表的主键字段
51     用了pk之后,就不需要知道当前表的主键字段叫什么
52     '''
53     # 删数据的第二种方式
54     user_obj = models.User.objects.filter(pk=1).first()
55     user_obj.delete()
56 
57 
58     # 修改方式一
59     models.User.objects.filter(pk=5).update(name='jason老师')
60     # 修改方式二
61     user_obj = models.User.objects.get(pk=6)
62     print(user_obj)  # get方法返回的直接说当前数据对象,但是如果数据不存在,则会直接报错,不会返回None
63     user_obj.name = 'egon老师'
64     user_obj.save()
复制代码

 

 (必知必会13条)

复制代码
 1 # 1.create()  创建数据并直接获取当前创建的数据对象
 2     # res = models.User.objects.create(name='阿兵', age=28)
 3     # res = models.User.objects.create(name='oscar', age=18)
 4     # res = models.User.objects.create(name='jerry', age=38)
 5     # res = models.User.objects.create(name='jack', age=88)
 6     # print(res)
 7 ------------------------------------
 8 # 2.filter()  根据条件筛选数据  结果是QuerySet [数据对象1,数据对象2]
 9     # res = models.User.objects.filter()
10     # res = models.User.objects.filter(name='jason')
11     # res = models.User.objects.filter(name='jason', age=19)
12 # 括号内支持多个条件但是默认是and关系
13 ------------------------------------
14 # 3.first() last()  QuerySet支持索引取值但是只支持正数 并且orm不建议你使用索引
15     # res = models.User.objects.filter()[1]
16     # res = models.User.objects.filter(pk=100)[0]  # 数据不存在索引取值会报错
17     # res = models.User.objects.filter(pk=100).first()  # 数据不存在不会报错而是返回None
18     # res = models.User.objects.filter().last()  # 数据不存在不会报错而是返回None
19 ------------------------------------
20 # 4.update()  更新数据(批量更新)
21     # models.User.objects.filter().update()     批量更新
22     # models.User.objects.filter(id=1).update() 单个更新
23 ------------------------------------
24 # 5.delete()  删除数据(批量删除)
25     # models.User.objects.filter().delete()      批量删除
26     # models.User.objects.filter(id=1).delete()  单个删除
27 ------------------------------------
28 # 6.all()     查询所有数据    结果是QuerySet [数据对象1,数据对象2]
29     # res = models.User.objects.all()
30 ------------------------------------
31 # 7.values()  根据指定字段获取数据    结果是QuerySet [{},{},{},{}],列表套字典
32     # res = models.User.objects.all().values('name')
33     # res = models.User.objects.filter().values()
34     # res = models.User.objects.values()
35 ------------------------------------
36 # 8.values_list()   根据指定字段获取数据  结果是QuerySet [(),(),(),()] 列表套元组
37     # res = models.User.objects.all().values_list('name','age')
38 ------------------------------------
39 # 9.distinct() 去重 数据一定要一模一样才可以 如果有主键肯定不行
40     # res = models.User.objects.values('name','age').distinct()
41 ------------------------------------
42 # 10.order_by()  根据指定条件排序  默认是升序 字段前面加负号就是降序
43     # res = models.User.objects.all().order_by('age')
44     # print(res)
45 ------------------------------------
46 11.get()   根据条件筛选数据并直接获取到数据对象!!
47 一旦条件不存在会直接报错 不建议使用!!!
48     res = models.User.objects.get(pk=1)
49     print(res)    # 直接获取到数据对象
50     res = models.User.objects.get(pk=100, name='jason')
51     print(res)      # 报错!!
52 ------------------------------------
53 12.exclude()
54 # 它包含了与所给筛选条件不匹配的对象,相当于filter的取反操作
55     res = models.User.objects.exclude(pk=1)
56     print(res)   # pk不等于1的所有对象
57 ------------------------------------
58 # 13.reverse()  颠倒顺序(被操作的对象必须是已经排过序的才可以)
59     # res = models.User.objects.all()
60     # res = models.User.objects.all().order_by('age')
61     # res1 = models.User.objects.all().order_by('age').reverse()
62     # print(res, res1)
63 ------------------------------------
64 14.count()     # 统计QuerySet结果集中的对象数量!!!
65      res = models.User.objects.all().count()
66      print(res)
67 ------------------------------------
68 15.exists()
69 # 判断结果集中是否含有数据 如果有则返回True 没有则返回False
70     res = models.User.objects.all().exists()
71     print(res)
72     res1 = models.User.objects.filter(pk=100).exists()
73     print(res1)
复制代码

 

 

【查看内部sql语句的方式】

 。

【双下划线查询】

 

复制代码
 1 '''
 2 只要还是queryset对象,就可以无限制的点queryset对象的方法!!!
 3    queryset.filter().values().filter().values_list().filter()...
 4 '''
 5 
 6 
 7     # 要求:查询年龄大于19岁的数据
 8     res = models.User.objects.filter(age__gt=19)
 9     print(res)
10     # 年龄小于25的数据
11     rqs = models.User.objects.filter(age__lt=25)
12     print(rqs)
13     # 大于等于   小于等于
14     rws = models.User.objects.filter(age__gte=25)
15     print(rws)
16     rrs = models.User.objects.filter(age__lte=25)
17     print(rrs)
18     # 年龄是18 或者20 或者 27的数据
19     rts = models.User.objects.filter(age__in=[18, 20, 27])
20     print(rts)
21     # 年龄在18到20之间的,首尾都能包括
22     rys = models.User.objects.filter(age__range=(18, 20))
23     print(rys)
24     # 查出名字里含有n的数据,模糊查询,默认区分大小写
25     rus = models.User.objects.filter(name__contains='n')
26     print(rus)
27     # 忽略大小写
28     ris = models.User.objects.filter(name__icontains='n')
29     print(ris)
30     # 名字以什么开头,以什么结尾
31     rps = models.User.objects.filter(name__startswith='n')
32     ros = models.User.objects.filter(name__endswith='n')
33     # 注册时间是2月份的数据,按照月份
34     ras = models.User.objects.filter(register_time__month=2)
35     print(ras)
36     # 按照年月日
37     rss = models.User.objects.filter(register_time__year=2022, register_time__month=12, register_time__day=12)
复制代码

【多表操作】

复制代码
 1 # 图书表
 2 class Book(models.Model):
 3     title = models.CharField(max_length=32)
 4     price = models.DecimalField(max_digits=5, decimal_places=2)
 5     publish_date = models.DateField(auto_now_add=True)
 6     # 外键,一对多
 7     publish = models.ForeignKey('Publish', on_delete=models.CASCADE)
 8     # 多对多
 9     authors = models.ManyToManyField(to='Author')
10     # F查询,增加两个字段
11     kucun = models.IntegerField(default=100)
12     maichu = models.IntegerField(default=99)
13 
14     # 自定义字段的使用
15     my_field = MyCharField(max_length=32, null=True)
16 
17     def __str__(self):
18         return '对象:%s' % self.title
19 
20 
21 # 出版社表
22 class Publish(models.Model):
23     name = models.CharField(max_length=32)
24     addr = models.CharField(max_length=32)
25     email = models.EmailField()  # varchar,该字段是给校验性组件看的,不是给model看的
26 
27     def __str__(self):
28         return '对象:%s' % self.name
29 
30 
31 # 作者表
32 
33 class Author(models.Model):
34     name = models.CharField(max_length=32)
35     age = models.IntegerField()
36     # 一对一
37     author_detail = models.OneToOneField('AuthorDetail', on_delete=models.CASCADE)
38 
39 
40 # 作者详情表
41 class AuthorDetail(models.Model):
42     phone = models.BigIntegerField()
43     addr = models.CharField(max_length=32)
复制代码

 

 (多表的增删改查)

复制代码
 1  # 一对多外键的增删改查
 2 
 3     # 增---方式一:创建一本书.直接写实际字段
 4     models.Book.objects.create(title='三国演义', price=123.23, publish_id=1)
 5     # 2.增---方式二: 虚拟字段,对象
 6     publish_obj = models.Publish.objects.filter(pk=2).first()  # 先查出有哪些对象
 7     models.Book.objects.create(title='红楼梦', price=100.23, publish=publish_obj)
 8 
 9     # 删:级联更新级联删除
10     models.Publish.objects.filter(pk=2).delete()
11 
12     # 修改--方式一
13     models.Book.objects.filter(pk=1).update(publish_id=2)
14     # 修改--方式二
15     publish_obj = models.Publish.objects.filter(pk=1).first()
16     models.Book.objects.filter(pk=1).update(publish=publish_obj)
17 
18 ----------------------------------------------------
19 # 多对多的增删改查
20 
21      # 如何给书籍添加作者?
22     # 前提是这第三张关联的表不是我们创建的,没办法通过点属性进行操作
23     book_obj = models.Book.objects.filter(pk=1).first()
24     print(book_obj.authors)  # .authors 获取的是一个对象列表,相当于已经到了第三张关系表了
25     book_obj.authors.add(1, 2)  # 书籍id为1的书籍绑定一个主键为1和2的作者
26     # 第二种关联方法
27     author_obj = models.Author.objects.filter(pk=1).first()
28     book_obj.authors.add(author_obj)
29     '''
30     add给第三张关系表添加数据,括号内既可以传数字,也可以传对象,并且都支持多个
31     book_obj.authors.add(2,3)
32     '''
33 
34     # 删除--方式一:
35     book_obj = models.Book.objects.filter(pk=2).first()
36     book_obj.authors.remove(2)  # 也支持同时删除多个
37     # 删除--方式二:对象
38     book_obj.authors.remove(3)  # remove给第三张关系表删除数据,括号内既可以传数字,也可以传对象,并且都支持多个
39 
40     # 修改 set()内必须放一个可迭代对象
41     book_obj = models.Book.objects.filter(pk=1).first()
42     book_obj.authors.set([1, 3])  # 把原理关联作者1,2改为1,3.  可迭代对象了也可以只放一个参数
43     # 这时候主键id也变了,是因为,先把原来的数据删除,然后再创建
44     # 第二种修改方法
45     author_obj = models.Author.objects.filter(pk=2).first()
46     book_obj.authors.set([author_obj])
47 
48     # 清空-----有一本书永久下架了,所有和它关联的数据都应该删除
49     book_obj = models.Book.objects.filter(pk=1).first()
50     book_obj.authors.clear()
复制代码

 

【正反向的概念】

复制代码
概念:
    正向
        外键字段在我手上,我去查你就是正向
        如书查出版社,外键字段在书那里
            book>>>>正向>>>>publish

    反向
         外键字段不在我手上,我去查你就是反向
           如出版社去查书,外键字段在书那里
                 publish<<<方向<<<<book

-----------------------------------------
-----------------------------------------

   口诀:正向查询按字段

    反向查询按表名小写_set

复制代码

(多表查询)

  子查询----------------------django(基于对象的跨表查询)

 

复制代码
 1 正向:
 2     # 1.查询书籍主键为1的出版社
 3     book_obj = models.Book.objects.filter(pk=1).first()
 4     # 书查出版社   正向
 5     res = book_obj.publish
 6     print(res)  # 对象:南京出版社
 7 
 8     # 2.查询书籍主键为2的书籍所有作者
 9     book_obj = models.Book.objects.filter(pk=2).first()
10     # rqs = book_obj.authors
11     # print(rqs)  # 拿到的是:app01.Author.None,
12     rqs = book_obj.authors.all()
13     print(rqs)  # 拿到两个作者对象: < QuerySet[ < Author: Author object(2) >, < Author: Author object(3) >] >
14 
15     # 3.查询作者为jason的电话号码
16     author_obj = models.Author.objects.filter(name='jason').first()
17     rws = author_obj.author_detail.phone
18     print(rws)  # 120
19 
20 
21 ------------------------------------
22 ------------------------------------
23 反向
24         # 4.查询出版社为南京出版社的书籍名称
25     publish_obj = models.Publish.objects.filter(name='南京出版社').first()
26     # 出版社查书---表名小写_set  反向
27     res = publish_obj.book_set.all()
28     print(res)
29 
30     # 5.查询作者为jason写过的书
31     author_obj = models.Author.objects.filter(name='jason').first()
32     ras = author_obj.book_set.all()
33     print(ras)
34 
35     # 6.查询手机号是120的作者名字
36     author_obj = models.Author.objects.filter(author_detail__phone=120).first()
37     print(author_obj.name)
38     '''
39     基于对象反向查询的时候
40         当你的查询结果可以有多个的时候,就必须加_set.all()
41         当查询结果只有一个的时候,不需要加_set.all()
42     '''
复制代码

 

 

  

  连表查询-------------------django(基于双下划线的跨表查询)

复制代码
 1     # 1。一行代码查询出jason的手机号__xxx
 2     res = models.Author.objects.filter(name='jason').values('author_detail__phone').first()
 3     print(res)
 4 
 5     # 2.查询书籍主键为1的出版社名称和书籍名称
 6     rzs = models.Book.objects.filter(pk=1).values('title', 'publish__name').first()
 7     print(rzs)
 8     # 不用.book去操作,第二种方法
 9     rxs = models.Publish.objects.filter(book__id='1').values('name', 'book__title').first()
10     print(rxs)  # {'name': '南京出版社', 'book__title': '三国演义'}
11 
12     # 3.查询书籍主键为1的作者姓名
13     rcs = models.Book.objects.filter(pk=1).values('authors__name').first()
14     print(rcs)
15     # 不用.book去操作,第二种方法
16     rvs = models.Author.objects.filter(book__id='1').values('name').first()
17     print(rvs)  # {'name': 'jason'}
18 
19     # 4.查询出jason的手机号和作者姓名,但是不用.Author
20     rbs = models.AuthorDetail.objects.filter(author__name='jason').values('phone', 'author__name')
21     print(rbs)
22     '''
23     models.AuthorDetail.objects.filter(author__name='jason') 拿作者姓名是jason的作者详情
24     '''
25 
26     # 5.查询书籍主键是1的作者的手机号
27     # book  author  author_detail,先跨到作者表去拿作者手机号
28     rns = models.Book.objects.filter(pk='1').values('authors__author_detail__phone')
29     print(rns)
复制代码

【聚合查询】

复制代码
 1   聚合查询(聚合函数的使用):需要先导入5个函数,基本上都配合分组使用
 2           不想分组,还想查询的用---aggregate
 3   
 4   只要跟数据库相关的模块,基本上都在django.db.models里面
 5 
 6  from django.db.models import Avg, Max, Min, Sum, Count
 7   
 8       # 1.查询书籍的平均价格,
 9       res = models.Book.objects.aggregate(Avg('price'))
10       print(res)
11       # 上述方法一次性使用
12      res = models.Book.objects.aggregate(Avg('price'), Max('price'), Min('price'), Sum('price'), Count('pk'))
13      print(res)
复制代码

 

 。

【分组查询】

 

复制代码
 1     # 分组查询   关键字:annotate
 2     # 按什么分组:models.后面是什么就是按照什么分组
 3     # 1.统计每一本是的作者个数
 4     res = models.Book.objects.values('title').annotate(count=Count('authors'))
 5     print(res)
 6     # 方式二
 7     rqs = models.Book.objects.annotate(author_num=Count('authors')).values('title', 'author_num')
 8     print(rqs)
 9     # 方式三:
10     rws = models.Book.objects.annotate(author_num=Count('authors__id')).values('title', 'author_num')
11     print(rws)
12 
13     # 2.统计每个出版社卖的最便宜的书的价格
14     rrs = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')
15     print(rrs)
16 
17     # 3.统计不止一个作者的图书
18     rts = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('title',
19                                                                                                     'author_num')
20     print(rts)
21 
22     # 4.查询每个作者出的书的总价格
23     rys = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name', 'sum_price')
24     print(rys)
25     '''
26     如果像按照指定的字段进行分组,那么该如何处理呢?
27         models.Book.objects.values('price).annotate()
28     
29     '''
复制代码

 

 。

【F和Q查询】

复制代码
 1 ''' 当需要字段和字段作比较的时候用F查询,当查询条件也就是等号右边不是明确的,查询条件也需要从数据库中获取 就需要使用F查询 '''
 2 
 3 ''' 当查询条件是 或 的时候 用Q查询,因为默认的filter参数都是且的关系 '''
 4 
 5 
 6 F查询
 7 
 8     # 1.查询出卖出大于库存数的书籍
 9     # F查询:能够获取表中某个字段对应的数据,F不能够直接做到字符串的拼接
10     from django.db.models import F
11 
12     res = models.Book.objects.filter(maichu__gt=F('kucun'))
13     print(res)
14 
15     # 2.将所有书籍的价格提升50元
16     rzs = models.Book.objects.all().update(price=F('price') + 50)
17     print(rzs)
18 
19     # 3.将所有书的名称后面加上爆款两个字,----F不能够直接做到字符串的拼接
20     from django.db.models import Value
21     from django.db.models.functions import Concat
22 
23     models.Book.objects.update(title=Concat(F('title'), Value('爆款')))
24 
25 =======================
26 Q查询
27 
28 # 1.查询卖出书大于100,或者价格小于200的书籍
29     # filter()内多个参数是and关系
30     from django.db.models import Q
31 
32     res = models.Book.objects.filter(Q(maichu__gt=100), Q(price__lt=200))  # , 和and同义
33     rqs = models.Book.objects.filter(Q(maichu__gt=100) | Q(price__lt=200))  # |是or同义
34     rws = models.Book.objects.filter(~Q(maichu__gt=100) | Q(price__lt=200))  # ~和not同义
35     print(res)
36     print(rqs)
37     print(rws)
38 
39     # Q的高阶用法,能够将查询条件的左边也变成字符串的形式
40     q = Q()
41     # and可以修改为or
42     q.connector = 'or'
43     q.children.append(('maichu__gt', 100))
44     q.children.append(('price__lt', 200))
45     rds = models.Book.objects.filter(q)  # 默认还是and关系
46     print(rds)
复制代码

【django开启事务】

复制代码
 1 事务(ACID):
 2 数据库事务指的则是作为单个逻辑工作单元执行的一系列操作(SQL语句) 功能:
 3 1、为数据库操作提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性
 4 的方法。
 5 2、当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干
 6 扰。
 7 这些操作要么全部执行,要么全部不执行。
 8 
 9 
10 事务的四大特性?
11 原子性 Atomicity
12 事务作为一个整体,包含在其中对于数据库的操作,要么全部执行,要么全部不执行。
13 例如:A给B转了100,A余额减100,刚转完系统崩溃,B收到钱款这一操作没有执行,
14 则整个事务回滚,100元退还到A的余额
15 
16 一致性 Consistency
17 事务应该确保数据库从一致状态转到另一个一致状态。
18 例如:转账行为中,一个人减了50元,另外一个人就应该加上这50元,而不能是40元。
19 其他一致状态的含义是数据库中的数据应满足完整性约束,例如字段约束不能为负数,
20 事务执行完毕后的该字段也同样不是负数。
21 
22 隔离性 Isolation
23 多个事务并发执行时,一个事务的执行应该不受其他事务执行的影响。
24 举例:A给B转100元和C给B转100元是独立的。
25 
26 持久性 Durability
27 成功执行的事务产生的结果应该被永久保留在数据库中
复制代码

 

1     from django.db import transaction
2 
3     # atomic原子性
4     with transaction.atomic():
5         ...
6         # 在with代码块内书写的所有orm操作都属于同一种事务
7     print('执行其他操作')

 。

 【常用字段】

复制代码
 1 AutoField       自增 字段类型
 2 括号内常见参数: primary_key=True
 3 -----------------------
 4 CharField    对应到数据库里面是varchar字段类型
 5 括号内常见参数: max_length
 6 ----------------------------------------------
 7 数字相关字段类型:
 8 IntegerField
 9 BigIntergerField
10 
11 DecimalField
12 括号内常见参数: max_digits    decimal_places
13 ----------------------------------------------
14 日期相关字段类型:
15 DateField  ---date
16 括号内常见参数: auto_now       auto_now_add
17 DateTimeField  ---datetime
18 括号内常见参数: auto_now       auto_now_add只记录创建记录的时间
19 ----------------------------------------------
20 布尔值字段类型:
21 
22 BooleanField
23     传布尔值自动存0或1
24 ----------------------------------------------
25 文本字段类型:
26 
27 TextField
28     存储大段文本,没有字数限制
29 ----------------------------------------------
30 邮箱字段类型:
31 
32 EmailField
33     存储邮箱格式数据
34 ----------------------------------------------
35 文件对象字段类型:
36 
37 FileField
38     传文件对象 自动保存到提前配置好的路径下并存储该路径信息!!
39     参数:
40             upload_to = ""      上传文件的保存路径
41             storage = None
42 # 存储组件,默认django.core.files.storage.FileSystemStorage
43 -----------------------------------------------------------
44 ORM还支持用户自定义字段类型:
45 
46     class MyCharField(models.Field):
47         def __init__(self, max_length, *args, **kwargs):
48             self.max_length = max_length
49             super().__init__(max_length=max_length, *args, **kwargs)
50 
51         def db_type(self, connection):  返回真正的熟练类型及各种约束条件
52             return 'char(%s)' % self.max_length
53 
54 
55     class User(models.Model):
56         name = models.CharField(max_length=32)
57         info = MyCharField(max_length=64)
复制代码

(ORM常用字段参数)

复制代码
 1 primary_key     主键
 2 verbose_name    注释
 3 max_length        字段长度
 4 max_digits     小数总共多少位
 5 decimal_places    小数点后面的位数
 6 auto_now        每次操作数据自动更新事件
 7 auto_now_add    首次创建自动更新事件后续不自动更新
 8 null            允许字段为空
 9 default            字段默认值
10 unique            唯一值
11 db_index        给字段添加索引
12 choices            当某个字段的可能性能够被列举完全的情况下使用
13 
14 to                关联表
15 to_field        关联字段(不写默认关联数据主键)
16 on_delete        当删除关联表中的数据时,当前表与其关联的行的行为。
17      1、models.CASCADE
18         级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
19     2、models.SET_NULL
20         当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
21     3、models.PROTECT
22         当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
23     4、models.SET_DEFAULT
24         当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
25     5、models.SET()
26         当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
27     6、models.DO_NOTHING
28         什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
复制代码

 

 

【orm补充】

only与defer 关键字 优化查询数据的时间

原来用all,要查所有字段的数据,然后封装到一个个对象里面去
现在用only就可以只查需要的几个字段数据,封装到一个个对象里面去,
这样查询数据的时间肯定减少了!!

复制代码
 1 关键字 only
 2 
 3 感觉像是all的升级版 all拿到的对象,里面有所有的字段名及对应的值
 4 only拿到的对象,里面只有括号里面指定的字段名及对应的值
 5 后续用对象点括号里面有的字段名不走sql查询,点没有的字段名会走sql查询!!!
 6 
 7 only方法的作用是:可以将括号里面所列举的字段封装到数据对象里面,
 8 当数据对象点击这些字段的时候是不会走sql查询的。
 9 
10 但是如果用数据对象去点击括号里面所没有填写的字段时,可以拿到数据,但是每点一次都会走一次sql数据库查询。
11 
12 需求升级:只获取指定字段的数据,并且结果还是一个的数据对象!!!
13 
14 res = models.Book.objects.only('title', 'price')
15 
16 print(res)         # queryset [数据对象、数据对象]
17 for obj in res:
18 print(obj.title)
19 print(obj.price)     # 点击括号内填写的字段 不走SQL查询
20 # 这种情况下用only获取到的对象,可以直接点击它括号里面的字段,不会走sql语句
21 
22 print(obj.publish_time)
23 # 也可以点击括号内没有的字段,也能获取到数据 ,但是会走SQL查询
24 
25 
26 =========================
27 关键字 defer 和only作用相反
28 
29 拿到的对象里面除了括号里面指定的字段名数据没有 ,其他的字段名数据都有!!!
30 后续用对象点括号里面有的字段名就会走sql查询,
31 点括号里面没有的字段名,不走sql查询!!!
32 
33 
34 res = models.Book.objects.defer('title', 'price')
35 print(res)  # queryset [数据对象、数据对象]
36 for obj in res:
37 print(obj.title)       # 点击括号内填写的字段 走SQL查询
38 print(obj.price)
39 print(obj.publish_time)      # 点击括号内没有的字段获取数据 不走SQL查询
复制代码

 select_related与prefetch_related 优化的sql执行的次数

复制代码
 1 select_related 底层是先连表后查询,再封装到对象里
 2 
 3 res = models.Book.objects.all()
 4 for obj in res:
 5     print(obj.title)    #  不走SQL查询,all的sql查询将所有数据都塞到每个对象里面了
 6 
 7     print(obj.publish.name)    # 当用数据对象点关联的出版社表里面的数据时,每次查询都需要走SQL查询
 8 
 9 ------------------------------------------------
10 ------------------------------------------------
11 
12 res = models.Book.objects.select_related('publish')  # 底层是先连表后查询封装
13 # 括号内支持填写一对多外键字段
14 # 提前先连表后查询数据,最后封装到一个个对象里面去!
15 for obj in res:
16     print(obj.publish.name)      # 不再走SQL查询!!!
17 
18 # 先将书表和出版社表拼到一起,然后把大表里面的所有数据封装到一个个书籍对像里面去
19 # 这样拿到的对象通过点的方式既可以点书表里面的所有字段,也可以点出版社表里面的所有字段
20 # 所以就不需要再走sql查询了!!!
21 
22 ------------------------------------------------
23 ------------------------------------------------
24 
25 res = models.Book.objects.select_related('authors')
26 # 括号内不支持填写多对多外键字段!!!
27 
28 
29 res1 = models.Author.objects.select_related('author_detail')
30 # 括号内也支持填写一对一外键字段
31 print(res1)
32 
33 
34 ============================
35 prefetch_related 底层是先子查询,再封装到对象里
36 
37 res = models.Book.objects.prefetch_related('publish')
38 # 底层是子查询,总共执行两条sql语句,第一条sql查询的结果作为第二条sql的查询条件
39 for obj in res:
40     print(obj.publish.name)  # 不再走SQL查询!
41 
42 # prefetch_related()  括号里面也是只能填写外键字段(除了多对多)
43 # 作用是 先把书表里面的所有数据查出来,然后基于书里面publish_id对应的值,再到出版式表里面,把对应的数据再查出来,之后封装起到一个个的书籍对象里面去
复制代码

 

posted on   认真的六六  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
点击右上角即可分享
微信分享提示