一、Django–ORM表设计格式(个人)

1、一对一建立外键

不同于django如需扩展原user表,将外键建在副表上。我更喜欢将外键建在主表上

外键名称 = models.OneToOneField(to='要连接的类名', to_field='字段', related_name='自定义反向查询关键字')
# 如不设置related_name,则反向查询时,默认使用语法'当前表名(小写)'

注:建表完成后,主表上会多一个字段,名为’被关联表名_id’

2、一对多建立外键

外键要写在一对多的 那个多的类里面。比如,一个学校对应很多老师,外键就要写在老师类里面

外键名称 = models.ForeignKey(to='要连接的类名',to_field='字段', related_name='自定义反向查询关键字')
# 如不设置related_name,则反向查询时,默认使用语法'当前表名(小写)_set'

注:建表完成后,主表上会多一个字段,名为’被关联表名_id’

3、多对多建立外键

外键建立在形式上的主表上。比如,一门课程由多个学生选修,而一个学生又可以选修多门课程,其中并无主副表之分,但我们主观上想到的是一个学生选修多门课程,所以学生表为主表,外键亦建在其中。

外键名称 = models.ManyToManyField(to='另一个类名')
# 如不设置related_name,则反向查询时,默认使用语法'当前表名(小写)_set'

注:
1、建表完成后,会生成一个中间表用来处理多对多关系,有三个字段,分别是默认生成的id、‘关联表名_id’、‘被关联表名_id’
2、上述django-orm通过OneToOneField、ForeignKey、ManyToManyField处理表关系只是其中一种形式,当然还有其它的。。。

二、基于orm的数据库表映射类

# 数据库表映射类下str与unicode到底写哪个?因django会在没有定义str()方法的时候自动提供一个str()方法调用unicode()方法,然后将结果转换为UTF-8编码的字符串对象。建议:只定义unicode()方法,需要的话让Django来处理字符串对象的转换。# 作家信息表
class Author(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=16)age = models.IntegerField()# 在Author上author_detail 变成了author_detail_id   这是一对一的外键写法# to后面加类名 to_field后面写类名中的字段名,选填,因为默认对应主键idauthor_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE, to_field='id')# 作家与书籍关系为多对多。这个books不是字段,他只是Author类里面的一个属性books = models.ManyToManyField(to='Book')def __unicode__(self):return self.nameclass Meta:db_table = 'author'  # 设置数据表名,否则的话,默认为《django-app》名称 + 下划线 + 类名verbose_name = '作家表'verbose_name_plural = verbose_name  # 这是为了防止admin后台显示的时候多出一个S# 选填:排序ordering = ["name", "age"]# 作家信息补充表
class AuthorDetail(models.Model):id = models.AutoField(primary_key=True)addr = models.CharField(max_length=16)tel = models.IntegerField()def __unicode__(self):return self.addrclass Meta:db_table = 'author_detail'  # 设置数据表名,否则的话,默认为《django-app》名称 + 下划线 + 类名verbose_name = '作家补充表'verbose_name_plural = verbose_name  # 这是为了防止admin后台显示的时候多出一个S# 选填:排序ordering = ["tel"]# 出版社表
class Publish(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=16)addr = models.CharField(max_length=16)def __unicode__(self):return self.nameclass Meta:db_table = 'publish'  # 设置数据表名,否则的话,默认为《django-app》名称 + 下划线 + 类名verbose_name = '出版社表'verbose_name_plural = verbose_name  # 这是为了防止admin后台显示的时候多出一个S# 选填:排序ordering = ["name"]# 书籍表
class Book(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=16)price = models.DecimalField(max_digits=6,decimal_places=2)# 在Book上publish变成了publish_id   这是一对多的外键写法publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, to_field='id')def __unicode__(self):return self.nameclass Meta:db_table = 'book'  # 设置数据表名,否则的话,默认为《django-app》名称 + 下划线 + 类名verbose_name = '书籍表'verbose_name_plural = verbose_name  # 这是为了防止admin后台显示的时候多出一个S# 选填:排序ordering = ["price"]

三、表查询(子查询&联表查询)

所谓的正向反向查询判断标准:外键所在表为主,被关联表为副。主查副即为正向查询,反之为反向查询
get、first获取到的是类对象,可以调用属性。all、filter&values获取到的都是QuerySet对象

3.1、一对一查询

正向查询

# 萧峰的住址# 初级用法author_obj = Author.objects.get(name='萧峰')# author_obj.外键名.要查字段  print(author_obj.author_detail.addr)# author_detail = models.OneToOneField(to='AuthorDetail', to_field='id')# 这个author_detail就是外键名
# 高级用法
# 类名.objects.filter(条件).values(外键名__字段)   "__" 这个是双下划线
ret = Author.objects.filter(name='萧峰').values('author_detail__addr')

反向查询

# 地址是大理的英雄名字# 初级用法author_detail_obj = AuthorDetail.objects.get(addr='大理')# author_detail_obj.要查询的表名(要小写).要查字段print(author_detail_obj.author.name)
# 高级用法
# 类名.objects.filter(另一个表名(小写)__条件).values(字段)   "__" 这个是双下划线
ret = AuthorDetail.objects.filter(addr='大理').values('author__name')

3.2、一对多查询

正向查询

# 出版天龙八部的出版社名字# 初级用法book_obj = Book.objects.get(name='天龙八部')# book_obj.外键名.要查字段    print(book_obj.publish.name)
# 高级用法
# objects.filter(外键名__条件).values(字段)   "__" 这个是双下划线
ret = Book.objects.filter(name='天龙八部').values('publish__name')

反向查询

 # 查询地址是西夏的出版社 出版的图书# 初级用法pub_obj = Publish.objects.get(addr='北京')# pub_obj.表名_set.all().values('name')   因为不止一个所以需要  表名_setprint(pub_obj.book_set.all().values('name'))
# 高级用法
# 类名.objects.filter(条件).values(另一个表名(小写)__字段)   "__" 这个是双下划线
ret = Publish.objects.filter(addr='北京').values('book__name')

3.3、多对多查询

正向查询

# 令狐冲写了哪些书# 初级用法author_obj = Author.objects.get(name='令狐冲')# author_obj.第三张表的属性.all().values(字段)print(author_obj.books.all().values('name'))  # 这个books虽然在Author类下面,但是它不是字段,只是属性.
# 高级用法
# 类名.objects.filter(属性__条件).values(字段)   "__" 这个是双下划线
ret = Author.objects.filter(name='令狐冲').values('books__name')

反向查询

# 天龙八部的作者都有谁# 初级用法book_obj = Book.objects.get(name='天龙八部')# book_obj.表名_set.all().values(字段)print(book_obj.author_set.all().values('name'))
# 高级用法
# 类名.objects.filter(条件).values(另一个表名__字段)   "__" 这个是双下划线
ret = Book.objects.filter(name='天龙八部').values('author__name')

3.4、多级联表查询

# 查询金庸出版社出版的所有的书名及作者名# 写法一
ret = Book.objects.filter(publish__name='金庸出版社').values('name','author__name')
# 写法二
ret = Publish.objects.filter(name='金庸出版社').values('book__name','book__author__name')
# 查询电话以6开头的作者出版过的书名及出版社名# 写法一
ret = Book.objects.filter(author__author_detail__tel__startswith='6').values('name','publish__name')
# 写法二
ret = Publish.objects.filter(book__author__author_detail__tel__startswith='6').values('name','book__name')
# 写法三
ret = AuthorDetail.objects.filter(tel__startswith='6').values('author__books__name','author__books__publish__name')

四、聚合查询, 分组查询, F查询, Q查询

4.1、聚合查询

# aggregate(*args, **kwargs)    是queryset的终结,queryset对象后面.aggregate  得到一个字典不再是queryset对象
# 计算所有书的平均价格from django.db.models import AvgBook.objects.all().aggregate(Avg('price'))   # 也可以给它起名字 aggregate(a = Avg('price'))  # 这个objects后面的 all()写不写都行  可以直接在控制器(models.Book.objects)后面写# 还可以不止生成一个聚合函数from django.db.models import Avg,Max,MinBook.objects.aggregate(Avg('price'),Max('price'),Min('price'))

4.2、分组查询

------------------单表查询(用上边的Book表)----------------------
# 查询每个出版社出版了多少本书      annotate里面写聚合函数(Max,Min,Avg,Count)  得到一个queryset对象Book.objects.values('publish').annotate(c=Count('id'))
# values里面写的是要分组的字段,每个出版社意思就是以出版社为分组, annotate里面写你要统计的, 而且必须是 别名=聚合函数这个格式------------------多表查询(用之前那些表) ---------------------查询每个出版社出版了多少本书
Publish.objects.values('name').annotate(c=Count('book__id'))
# 下面这个方法比较常用
Publish.objects.annotate(c=Count('book__id')).values('name','c')
# 如果用上边的那个方法出现关于group by的错误的话,需要进行一下操作:进入mysql里执行SELECT @@GLOBAL.sql_mode;  看看里面是否有    ONLY_FULL_GROUP_BY参数,如果有的话需要到配置文件中(my.ini或者是mysql.cnf)修改sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'然后重启mysql.

4.3、F查询(可以进行两个字段的比较)

# 比如说在Book表里面加上评论数comment_num 和点赞数support_num# 查询评论数大于点赞数的书from django.db.models import FBook.objects.filter(comment_num__gt=F('support_num'))# django 还支持F()对象之间以及F()对象与常数之间的加减乘除Book.objects.filter(comment_num__gt=F('support_num')*2)# 也可以用F()来进行修改# 把每本书的价格添加1000Book.objects.update(price=F('price')+1000)

4.4、Q查询

像filter()中的条件一起查询的时候都是and, 如果想要有or的关系就需要用到Q查询

Q对象可以使用$(and)   |(or)   ~(not) 操作组合起来. 当一个操作符用在两个Q对象上面时,这两个Q对象由于操作符的作用就变成了一个新的对象.
# 查询作者名字为萧峰或者段誉出版的书
Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉'))# 可以组合其他的操作符进行操作
# 查询作者是萧峰或者是段誉价格不高于100的书
Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉')& ~Q(price__gt=100))# 如果有关键字参数和Q查询同时在筛选条件里面,Q查询必须要写到关键字参数前面
# 查询作者名字是萧峰或者是段誉的价格为100 的书
Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉'),price=100)
# 这个关键字参数要写到Q查询的后面,中间用逗号隔开,表示and的意思

五、python脚本中调用Django环境(django外部脚本使用models)

import osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")import djangodjango.setup()from app01 import models  #引入也要写在上面三句之后books = models.Book.objects.all()print(books)

六、总结

假设一对一为①,一对多为②,多对多为③

  • 正向查询
    ①②使用外键名称,③使用属性名称;其中关联字名称都在类中定义了
  • 反向查询
    ②③使用类/表名(小写)_set,①使用类/表名(小写);

七、学习参考地址

八、只讲了查询怎么够,来看增、删、改操作吧

九、好看那就点个赞再走吧!

django orm基本操作一相关推荐

  1. Django ORM操作

    Django ORM操作 一般操作 看专业的官网文档,做专业的程序员! 必知必会13条 <1> all(): 查询所有结果<2> get(**kwargs): 返回与所给筛选条 ...

  2. django mysql orm教程_带你了解Django ORM操作(基础篇)

    前言 在日常开发中,需要大量对数据库进行增删改查操作. 如果头铁的话,使用原生SQL是最好的,毕竟性能又高,又灵活. 但是通常情况下,我们不是太需要那么苛刻的性能,也没有那么多刁钻的需求用原生SQL ...

  3. Django ORM那些相关操作

    一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/         官网文档 常用的操作 <1> all() ...

  4. django orm级联_Django数据表关联关系映射(一对一、一对多、多对多)

    我们知道涉及到数据表之间的对应关系就会想到一对一.一对多.多对多,在学习 MySQL 数据库时表关系设计是需要重点掌握的知识.Django 中定义了三种关系类型的字段用来描述数据库表的关联关系:一对多 ...

  5. django ORM相关的那些操作汇总

    必知必会13条 <1> all(): 查询所有结果<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象<3> get(**kwargs): ...

  6. django ORM中的RelatedManager(关联管理器)

    关联管理器应用在 一对多的表 或者 多对多的表 多对多表中的用法: 在多对多的表中 正向查询 #基于对象的查询 #正查 # author_obj = Author.objects.get(id=1) ...

  7. Django ORM

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  8. Django ORM 知识点总结

    Query是如何工作的 Django QuerySet是懒执行的,只有访问到对应数据的时候,才会去访问数据库.另外如果你再次读取查询到的数据,将不会触发数据库的访问,而是直接从缓存获取. 比如 # 这 ...

  9. Django - ORM操作

    Django - ORM操作 一. 必知必会13条 单表查询之神奇的双下划线 二. ForeignKey操作 正向查找 反向操作 三. ManyToManyField 四. 聚合查询和分组查询 聚合 ...

最新文章

  1. 汉字转换成html,汉字与16进制、汉字与Html转义符的转换
  2. 关于 通过http请求 无法访问Linux下的ftp服务的解决办法!
  3. 处理大并发之一 对异步非阻塞的理解
  4. python打包的exe如何免杀_如何使用Python进行Payload免杀
  5. 微信养猫小程序源码搭建教程
  6. C11全系产品涨价后 零跑汽车宣布T03全系车型调价
  7. 【linux】linux 查找 或者 搜索 文件 find
  8. ROS入门-12.服务端Server的编程实现
  9. 30多岁的男人是创业,还是选择找个踏实的工作?
  10. Ajax.Net之数据类型
  11. 【iCore3应用】基于iCore3双核心板的编码器应用实例
  12. typescript探索(一)
  13. 开发者论坛一周精粹(第六十三期) WHM自动脚本修复ssh问题
  14. UML建模工具2021年8-11月更新(共15款)
  15. 16-20信息安全工程师上午题总结
  16. 多目标跟踪算法SOART
  17. 特殊符号大全(无穷的想象力)
  18. 文件夹双击提示找不到应用程序,右键可以打开(已解决)
  19. 怎样使用Markdown输入数学公式
  20. 阅读---读吴军博士《态度》有感

热门文章

  1. 老子说:知其雄,守其雌
  2. 【其他】逻辑、逻辑推理概念
  3. 七夕王者服务器维护什么时间结束,王者荣耀2020七夕活动什么时候结束?七夕情人节活动结束时间[多图]...
  4. 51nod_1265 四点共面
  5. 同态基本定理及其应用
  6. 红旗系统linux2.6.32屏保咋设置,红旗Linux桌面操作系统 V11社区预览版发布,附新特性介绍...
  7. 红旗 Linux 桌面操作系统 11 来了
  8. token值过期的处理
  9. R语言 Matrix的使用
  10. mysql断电同步不起作用_记一次mysql主从同步因断电产生的不能同步问题 1236 and 1032...