• Django——模型层补充


    django中如何开启事务

    1. '''
    2. # 事务的四大特性:
    3. # 简称: ACID
    4. # A: 原子性
    5. 事务对数据的修改操作要么同时成功, 要么一个都别想成功(回滚)
    6. # C: 一致性
    7. 事务的执行必然是从一个一致性的状态, 转变到另一个一致性的状态.
    8. # I: 隔离性
    9. 对于并发的事务, 每个事务之间是互相隔离的, 互不影响的. 如果是争对同一份数据的修改操作, 那么将并发变成串行, 牺牲了效率, 但是保证了数据的安全.
    10. # D: 持久性:
    11. 事务执行完毕对数据的修改操作是永久性的. 即便在数据库管理系统异常, 提交的结果对数据的修改也是永久的.
    12. # 原生SQL中的事务操作步骤
    13. 1. 开启 start transaction;
    14. 2. 回滚 rollback;
    15. 3. 确认 commit;
    16. '''
    17. from django.db import transaction
    18. try:
    19. with transaction.atomic():
    20. # ORM执行SQL语句
    21. ...
    22. # 在with代码快内书写的所有orm操作都是属于同一个事务
    23. except Exception as e:
    24. print(e)
    25. print('执行其他操作')

    orm语句的特点: 惰性查询

    1. """
    2. 如果你仅仅只是书写了orm语句 在后面根本没有用到该语句所查询出来的参数
    3. 那么orm会自动识别 直接不执行
    4. 惰性: res = models.Book.objects.all()
    5. 执行: print(res)
    6. """

    Django ORM执行原生SQL

    1. '''
    2. extra: 标识要做格外的操作
    3. select={'publish_date': 'date_format(publish_date, "%%Y-%%m")'}: 执行原生的sql语句用到原生sql日期函数date_format
    4. publish_date: 定义一个key, 通过values后面可以拿到结果. 类始于annotate分组一样
    5. '''
    6. # 需求: 查询数据名称和出版时间(年-月)
    7. res = models.Book.objects.extra(select={'publish_date': 'date_format(publish_date, "%%Y-%%m")'}).values('name', 'publish_date')
    8. print(res) #

    数据库查询优化

    1. only 和 defer

    1. '''
    2. 使用: 直接在objects后面连用
    3. 返回: only 和 defer都返回QuerySet对象
    4. 区别:
    5. only: only括号内指定的字段, 在被查询的时候不会走数据库.
    6. defer: defer括号内指定的字段, 在被查询的时候会走数据库
    7. 特殊: 如果仅仅使用all. 没有执行结果它是惰性的, 但是一旦执行过一次. 第二次拿到all的返回值. 是不需要重新走数据库
    8. '''
    9. # 1. only
    10. # res = models.Publish.objects.only('name')
    11. res = models.Publish.objects.all()
    12. print(res) # , ]>
    13. for i in res:
    14. print(i.name) # 点击only括号内的字段不会走数据库
    15. for i in res:
    16. print(i.addr) # 点击only括号内没有的字段会重新走数据库. 如果是all的情况就不需要走.
    17. """
    18. (0.001) SELECT `app01_publish`.`id`, `app01_publish`.`addr` FROM `app01_publish` WHERE `app01_publish`.`id` = 1; args=(1,)
    19. (0.001) SELECT `app01_publish`.`id`, `app01_publish`.`addr` FROM `app01_publish` WHERE `app01_publish`.`id` = 2; args=(2,)
    20. """
    21. # 2. defer
    22. res = models.Publish.objects.defer('name')
    23. print(res) # , ]>
    24. for i in res:
    25. print(i.name) # 点defer括号内的字段会走数据库
    26. '''
    27. (0.000) SELECT `app01_publish`.`id`, `app01_publish`.`name` FROM `app01_publish` WHERE `app01_publish`.`id` = 1; args=(1,)
    28. (0.000) SELECT `app01_publish`.`id`, `app01_publish`.`name` FROM `app01_publish` WHERE `app01_publish`.`id` = 2; args=(2,)
    29. '''
    30. for i in res:
    31. print(i.addr) # 点defer括号内的字段不会走数据库

    2. select_related 和 prefetch_related

    1. '''
    2. 使用: 直接在objects后面连用
    3. 返回: only 和 defer都返回QuerySet对象
    4. 区别:
    5. select_related: 内部使用连表查询.
    6. !!注意:!! 括号内只能放外键字段. 且只支持一对一, 一对多的表关系. 多对多不支持.
    7. 内部通过1次性将2表查询出来封装成对象中, 下次查询这2表就无序走数据库了.
    8. prefetch_related: 内部使用子查询.
    9. 内部通过2次性将子查询结果查询出封装成对象中.下次查询这2表就无序走数据库了. (感觉视角: 感觉是一次性搞定的)
    10. '''
    11. # 1. select_related 连表查询
    12. '''
    13. select_related内部直接先将Author与author_detail表连起来 然后一次性将大表里面的所有数据, 全部封装给查询出来的对象.
    14. 这个时候对象无论是点击book表的数据还是publish的数据都无需再走数据库查询了
    15. '''
    16. res = models.Author.objects.select_related('author_detail')
    17. for i in res:
    18. print(i.author_detail.phone)
    19. '''
    20. (0.001) SELECT `app01_author`.`id`, `app01_author`.`name`, `app01_author`.`age`, `app01_author`.`author_detail_id`, `app01_authordetail`.`id`, `app01_authordetail`.`phone`, `app01_authordetail`.`addr` FROM `app01_author` INNER JOIN `app01_authordetail` ON (`app01_author`.`author_detail_id` = `app01_authordetail`.`id`); args=()
    21. '''
    22. # 下次查询这2表就无序走数据库了.
    23. for i in res:
    24. print(i.author_detail.phone)
    25. # prefetch_related 子查询
    26. '''
    27. prefetch_related该方法内部其实就是子查询
    28. 将子查询查询出来的所有结果也给你封装到对象中
    29. 给你的感觉好像也是一次性搞定的
    30. '''
    31. res = models.Author.objects.prefetch_related('author_detail')
    32. for i in res:
    33. print(i.author_detail.phone)
    34. '''
    35. (0.000) SELECT `app01_author`.`id`, `app01_author`.`name`, `app01_author`.`age`, `app01_author`.`author_detail_id` FROM `app01_author`; args=()
    36. (0.001) SELECT VERSION(); args=None
    37. (0.000) SELECT `app01_authordetail`.`id`, `app01_authordetail`.`phone`, `app01_authordetail`.`addr` FROM `app01_authordetail` WHERE `app01_authordetail`.`id` IN (1, 2, 3); args=(1, 2, 3)
    38. '''
    39. # 下次查询这2表就无序走数据库了.
    40. for i in res:
    41. print(i.author_detail.phone)

    in_bulk 根据主键ID进行查找

    1. dic_obj = models.Book.objects.in_bulk([1, 2])
    2. print(type(dic_obj)) #
    3. for pk, book_obj in dic_obj.items():
    4. print(pk, book_obj.name)
    5. '''
    6. 1 西游记
    7. 2 水浒传
    8. '''

  • 相关阅读:
    思维模型 协议
    Java基础:Object类、常用API
    web前端课程设计 HTML+CSS+JavaScript旅游风景云南城市网页设计与实现 web前端课程设计代码 web课程设计 HTML网页制作代码
    Spring Boot
    STM32照相机实验
    FasterNet 与 RT-DTER 的 碰撞,打造 Faster-DTER 目标检测网络 | 《Run, Don’t Walk: Chasing Higher FLOPS for Faster 》
    阶段性测试完成后,你进行缺陷分析了么?
    时序数据库-13-[IoTDB]的原理解析
    怎样利用物联网技术监管危废固废,要遵循哪些原则,有什么要求?
    MySQL精简复习
  • 原文地址:https://blog.csdn.net/m0_71115526/article/details/134462808