Django--ORM 多表查询

一 . 建立外键

  一对一建立外键

外键名称 = models.OneToOneField(to=‘要连接的类名‘, to_field=‘字段‘)

  一对多建立外键

外键名称 = models.ForeignKey(to=‘要连接的类名‘,to_field=‘字段‘)

# 外键要写在一对多的 那个多的类 下面,比如一个老师对应很多学生,外键就要写在学生的下面

  多对多建立外键

外键名称 = models.ManyToManyField(to=‘另一个类名‘)

# 这个外键名称(属性)要写在其中一个类的下面,然后to=另一个类名, 这个外键就相当于第三张表(多对多建立外键必须通过第三张表)

二 . 多表查询(基于子查询)

    # models.py创建表
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    age = models.IntegerField()
    # to后面加类名 to_field后面写类名中的字段名   这是一对一的外键写法
    author_detail = models.OneToOneField(to=‘AuthorDetail‘, to_field=‘id‘)
    def __str__(self):
        return self.name

class AuthorDetail(models.Model):
    id = models.AutoField(primary_key=True)
    addr = models.CharField(max_length=16)
    tel = models.IntegerField()

class Publish(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    addr = models.CharField(max_length=16)

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‘,to_field=‘id‘)
    #  这个authors不是字段,他只是Book类里面的一个属性  这是多对多的建立第三张表的写法
    authors = models.ManyToManyField(to=‘Author‘)

  

  对authors(第三张表的操作)

# 给id=1的书籍添加id=5和id=6这两个作者
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.add(*[5, 6])   #  数字的类型是int或者str都行

# 把id=1的书籍的作者全部删掉
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.clear()

# 把id=1的书籍中的id=5和id=6的这两个作者删掉
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.remove(*[5, 6])

# 把id=1的书籍中的作者名更新成id=7和id=8这两个作者
book_obj = models.Book.objects.filter(id=1)[0]
book_obj.authors.set([7, 8])
# set 不能用*[7, 8]      set的执行流程是先把作者全部删除,然后添加[7, 8]

  一对一正向查询(外键在哪个表,他找别人就是正向)

# 萧峰的住址
    author_obj = models.Author.objects.get(name=‘萧峰‘)
    # author_obj.外键名.要查字段
    print(author_obj.author_detail.addr)

   # author_detail = models.OneToOneField(to=‘AuthorDetail‘, to_field=‘id‘)
    # 这个author_detail就是外键名

  一对一反向查询(没有外键的表查询有外键的表就是反向查询)

# 地址是大理的英雄名字
    author_detail_obj = models.AuthorDetail.objects.get(addr=‘大理‘)
    # author_detail_obj.要查询的表名(要小写).要查字段
    print(author_detail_obj.author.name)

  一对多正向查询

 # 出版天龙八部的出版社名字
    book_obj = models.Book.objects.get(name=‘天龙八部‘)
    # book_obj.外键名.要查字段
    print(book_obj.publish.name)

  一对多反向查询

 # 查询城市是西夏的出版社 出版的图书
    pub_obj = models.Publish.objects.get(city=‘西夏‘)
    # pub_obj.表名_set.all().values(‘name‘)   因为不止一个所以需要  表名_set
    print(pub_obj.book_set.all().values(‘name‘))

  多对多正向查询

# 天龙八部的作者都有谁
    book_obj = models.Book.objects.get(name=‘天龙八部‘)
    # book_obj.第三张表的属性.all().values(字段)
    print(book_obj.authors.all().values(‘name‘))  # 这个authors虽然在Book类下面,但是它不是字段,只是属性.

  多对多反向查询

# 令狐冲写了哪些书
    author_obj = models.Author.objects.get(name=‘令狐冲‘)
    # author_obj.表名_all().values(字段)
    print(author_obj.book_set.all().values(‘name‘))

三 .基于双下划线跨表查询(基于join)

  正向查询按照外键名,反向查询按照表名(小写), 和上面的一样,外键字段在哪个表中, 他找别人就是正向,相反就是反向查询

    # 一对一查询
    # 查询萧峰作者的电话号
# 正向查询     按照外键    "__" 这个是双下划线
# models.类名(表名).objects.filter(条件).values(外键名__字段)
ret = models.Author.objects.filter(name=‘萧峰‘).values(‘author_detail__tel‘)

# 反向查询   按照类名(小写)
# models.类名.objects.filter(另一个类名(小写)__条件).values(字段)
ret = models.AuthorDetail.objects.filter(book__name=‘萧峰‘).values(‘tel‘)

    # 一对多查询
    # 金庸出版社出版过的所有书籍的名字
# 正向查询  按照外键
# models.类名.objects.filter(外键名__条件).values(字段)
ret = models.Book.objects.filter(publish__name=‘金庸出版社‘).values(‘name‘)

# 反向查询 按照类名(小写)
# models.类名.objects.filter(条件).values(另一个类名(小写)__字段)
ret = models.Publish.objects.filter(name=‘金庸出版社‘).values(‘book__name‘)

    # 多对多查询
    # 萧峰这个作者写了哪几本书
# 正向查询  按照外键
# models.类名.objects.filter(外键__条件).values(字段)
ret = models.Book.objects.filter(authors__name=‘萧峰‘).values(‘name‘)

# 反向查询  按照类名
# models.类名.objects.filter(条件).values(另一个类名__字段)
ret = models.Author.objects.filter(name=‘萧峰‘).values(‘book__name‘)

    # 连续跨表查询
    # 查询金庸出版社出版的所有的书名及作者名
# 正向查询
ret = models.Book.objects.filter(publish__name=‘金庸出版社‘).values(‘name‘,‘authors__name‘)

# 反向查询
ret = models.Publish.objects.filter(name=‘金庸出版社‘).values(‘book__name‘,‘book__authors__name‘)
# 由于Author和Publish两个表没有外键关系所以需要通过Book表找到作者名

    # 电话以6开头的作者出版过的书名及出版社名
# 正向查询
ret = models.Book.objects.filter(authors__author_detail__tel__startswith=‘6‘).values(‘name‘,‘publish__name‘)    

# 反向查询
# 方法一
ret = models.Publish.objects.filter(book__authors__author_detail__tel__startswith=‘6‘).values(‘name‘,‘book__name‘)

# 方法二
ret = models.AuthorDetail.objects.filter(tel__startswith=‘6‘).values(‘author__book__name‘,‘author__book__publish__name‘)
# 由于Author与Book是多对多的关系,并且authors写在Book下面,所以通过author往回找的时候直接author__book.

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

  聚合查询

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

# 还可以不止生成一个聚合函数
    from django.db.models import Avg,Max,Min
    models.Book.objects.aggregate(Avg(‘price‘),Max(‘price‘),Min(‘price‘))

  分组查询

------------------单表查询(用上边的Book表)----------------------
# 查询每个出版社出版了多少本书      annotate里面写聚合函数(Max,Min,Avg,Count)  得到一个queryset对象

models.Book.objects.values(‘publish‘).annotate(c=Count(‘id‘))
# values里面写的是要分组的字段,每个出版社意思就是以出版社为分组, annotate里面写你要统计的, 而且必须是 别名=聚合函数这个格式

------------------多表查询(用之前那些表) ---------------------

查询每个出版社出版了多少本书
models.Publish.objects.values(‘name‘).annotate(c=Count(‘book__id‘))
# 下面这个方法比较常用
models.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.

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

# 比如说在Book表里面加上评论数comment_num 和点赞数support_num
    # 查询评论数大于点赞数的书
    from django.db.models import F
    models.Book.objects.filter(comment_num__gt=F(‘support_num‘))

    # django 还支持F()对象之间以及F()对象与常数之间的加减乘除
    models.Book.objects.filter(comment_num__gt=F(‘support_num‘)*2)

    # 也可以用F()来进行修改
    # 把每本书的价格添加1000
    models.Book.objects.update(price=F(‘price‘)+1000)

  Q查询

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

Q对象可以使用$(and)   |(or)   ~(not) 操作组合起来. 当一个操作符用在两个Q对象上面时,这两个Q对象由于操作符的作用就变成了一个新的对象.
# 查询作者名字为萧峰或者段誉出版的书
models.Book.objects.filter(Q(authors__name=‘萧峰‘)|Q(authors__name=‘段誉‘))

# 可以组合其他的操作符进行操作
# 查询作者是萧峰或者是段誉价格不高于100的书
models.Book.objects.filter(Q(author__name=‘萧峰‘)|Q(author__name=‘段誉‘)& ~Q(price__gt=100))

# 如果有关键字参数和Q查询同时在筛选条件里面,Q查询必须要写到关键字参数前面
# 查询作者名字是萧峰或者是段誉的价格为100 的书
models.Book.objects.filter(Q(author__name=‘萧峰‘)|Q(author__name=‘段誉‘),price=100)
# 这个关键字参数要写到Q查询的后面,中间用逗号隔开,表示and的意思

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

import os

if __name__ == ‘__main__‘:
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    from app01 import models  #引入也要写在上面三句之后

    books = models.Book.objects.all()
    print(books)

原文地址:https://www.cnblogs.com/uiys/p/10673366.html

时间: 2024-10-13 10:43:32

Django--ORM 多表查询的相关文章

django orm 关联表查询

django orm 关联表数据,即sql的多表查询 例如两个表: Apply表中定义了字段position为foreignkey指向job表的id字段, 1.通过job表查找子表apply的字段信息: job.objects.values( 'id', 'job_type', 'apply__date_created') 连接符为小写的子表tablename+双下线+子表字段名即:apply__date_created 表示寻找Apply表中的date_created字段 等价于后台的SQL:

python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)

12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_demo.settings") import django django.setup() # 启动Django项目 from app01 import models #返回QuerySet对象的方法: r

ORM跨表查询

首先,在项目中添加我们要查询的模型,并插入数据 在django根目录下创建一个查询的py文件,供我们测试 ORM跨表查询可以分为基于  对象的查询(子查询)  和基于 queryset(双下划线__) 的查询 基于对象的查询(子查询) 一对多的查询 正向查询:在有关联字段的表向被关联的表查询 一对多的正向查询(正向查询按字段) 查询名为 python开天辟地 这本书的出版社的邮箱 book_obj = models.Book.objects.filter(title="python开天辟地&qu

ORM::联表查询

按顺序来一步一步走: 第一先建立好数据库:我的数据库是mysql数据库,数据库共分为以下几个表: users  用户表(刚开始的时候我用的是user表名,由于kohana有喜欢建立model时在后面加复数的习惯,但是估计 user这个名字已经被占用了,指定$_table_name="user"也不行) posts 帖子 数据库导出代码如下: -- phpMyAdmin SQL Dump -- version 3.4.10.1deb1 -- http://www.phpmyadmin.n

请教如何用 peewee 实现类似 django ORM 的这种查询效果。

本人新入坑的小白,如有不对的地方请包涵~~~! 在 django 中代码如下:模型定义: class Friends(models.Model): first_id = models.IntegerField() second_id = models.IntegerField() class Meta: unique_together=('first_id', 'second_id',) 查询语句如下: friend_list_info = [] friend_list1 = Friends.o

Django开发之路 二(django的models表查询)

django的models表查询 一.单表查询 (1) all(): 查询所有结果 # 返回的QuerySet类型 (2) filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 #返回的QuerySet类型 (3) get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个, #返回的models对象 如果符合筛选条件的对象超过一个或者没有都会抛出错误. (4) exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 #返回的Query

Django 之多表查询 与多表的使用

1.django的多表查询 主要区分为: 正向查询    逆向查询 1. 多表查询: 是一个复杂的查询,他分为对象查询和__模糊查询两种方式 2. 多表查询: 又分为 一对一查询, 一对多查询, 多对多查询 三种方式 3. 多表查询: 分为正向查询 与 逆向查询, 正向查询 是根据 这个表中的外键属性名开始出发查询的跨表查询 逆向查询 是根据 根据关联表的 类名 小写 开始 进行跨表查询 4. 多表查询: 外键的存放位置如下: # 一对多:出版社(一) 书籍(多,外键在多的一方,依赖于出版社)

Django 【补充】ORM跨表查询补充

models.Book.objects.filter(**kwargs): querySet [obj1,obj2]models.Book.objects.filter(**kwargs).values(*args) : querySet [{},{},{}]models.Book.objects.filter(**kwargs).values_list(title) : querySet [(),(),()] 跨表查询总结: 1.创建表 class Book(models.Model): ti

Django ORM 多表操作

创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的关系(one-to-one) 出版商模型:出版商有名称,所在城市以及email. 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-

ORM单表查询,跨表查询,分组查询

单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11.22.33的数据models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven")