ORM正向和反向查询

ORM正向和反向查询

表结构

from django.db import models

# Create your models here.
class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)

    publisher = models.ForeignKey('Publisher', related_name='person_book', related_query_name='ooxx')

插入数据

# Book表
id   title  pubtime          person_id
   书1    1533225600000    1
   书2    1533225600000    1
   书3    1534435200000    1
   书4    1535644800000    2
   书5    1535126400000    3
# Publisher表
id   name    
1    出版社1    
2    出版社2    
3    出版社3

正向查询: 外键所在表去查另一张表,Book >> Publisher

反向查询:普通表去查外键所在的表,Publisher >> Book

正向查询,基于对象跨表查询

book_obj = models.Book.objects.all()  # 取到书籍对象
book_obj.publisher.name   # 书籍的出版社名字,html
book_obj.person.id   # 书籍的出版社id,html

跨表查询,利用双下划线跨表查询

models.Book.objects.filter(id=1).values('publisher__name')  # 查询id是1的书的出版社的名字,一条双下划线就是跨一张表
models.Book.objects.filter(id=1).values_list('publisher__name')  

反向查询

对象查询 obj.表名_set()

publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
ret = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有数
for i in ret:  # 循环对象
    print(i.name)  # 打印出每一个书的书名
publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
titles = books.values_list("name")  # 找到第一个出版社出版的所有书的书名
print(titles)
因为使用了releted_name,就是用person_book代替了表字段名字
表字段person = models.ForeignKey(Person, related_name='person_book')
所以这一这样写
books = publisher_obj.person_book.all()
titles = books.values_list('name')
print(titles)
如果表字段person = models.ForeignKey(Person, related_name='person_book',related_query_name="xxoo")
related_query_name="xxoo",这里表示跨表查询xxoo代替表的名字book
books = publisher_obj.ooxx_set.all()

基于双下划线

ret = models.Publisher.objects.filter(id=1).values_list('person_book__name')
person_book是通过releted_name给对应关系起的名字,通过person_book就找到了关联的表,再通过双下划线找到name
print(ret)

附带django里面脚本的代码

import os

if __name__ == '__main__':
    # 加载Django项目的配置信息
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目名.settings")
    # 导入Django,并启动Django项目
    import django
    django.setup()

    from app01 import models
    # 查询id为1的出版社出版的所有书的name
    ret = models.Publisher.objects.filter(id=1).values_list('person_book__name')
    print(ret)
<think>嗯,用户想了解如何在Tortoise ORM中进行关联查询。首先,我需要回忆一下Tortoise ORM的相关知识。记得Tortoise ORM是一个异步的ORM,支持关联模型,比如外键、一对一多对多关系。用户需要具体的用法示例,所以应该从定义模型开始,然后展示如何查询关联数据。 首先,定义模型是关键。比如,用户可能有AuthorBook两个模型,通过外键关联。需要确保模型类继承tortoise.models.Model,并且正确设置外键字段,比如author = fields.ForeignKeyField。然后,在查询时,可以使用prefetch_related或fetch_related来获取关联的数据。比如,获取作者及其所有书籍,或者根据书籍查作者。 接下来,要考虑如何编写示例代码。比如,先初始化Tortoise ORM,然后创建模型实例,保存到数据库,再进行查询。示例代码需要包括模型的导入、初始化数据库连接、定义模型结构、创建数据,最后执行关联查询。需要注意异步函数的使用,比如async with in transaction可能会用到。 另外,用户可能想知道不同关联类型的处理方式,比如一对多、多对多。可能需要分别举例说明。例如,多对多关系可能需要一个中间模型,或者使用ManyToManyField。在查询时,使用prefetch_related来获取多对多关联的数据。 还需要注意引用中的信息。参考引用[2]提到使用prefetch_related来减少数据库访问次数,提高性能,这应该在关联查询时使用。所以,在示例中需要展示如何正确使用prefetch_related方法,避免N+1查询问题。 可能用户会遇到的问题包括模型定义错误、关联字段名称不正确,或者异步查询未正确使用await。在解答时需要提醒常见的注意事项,比如确保外键字段正确设置,关联名称一致,以及异步操作的必要性。 最后,生成相关问题。用户可能想了解更深入的优化方法,或者如何处理复杂的关联查询,比如过滤关联数据、排序等。根据这些,可以生成相关问题,帮助用户进一步学习。</think>### Tortoise ORM关联查询使用方法 #### 一、模型定义 先创建具有关联关系的模型,以下示例包含$Author$(作者)$Book$(书籍)的一对多关系: ```python from tortoise import fields, models class Author(models.Model): id = fields.IntField(pk=True) name = fields.CharField(max_length=50) class Book(models.Model): id = fields.IntField(pk=True) title = fields.CharField(max_length=100) author = fields.ForeignKeyField("models.Author", related_name="books") ``` #### 二、基础关联查询 1. **正向查询**(从书查作者): ```python async def get_book_with_author(): book = await Book.filter(title="Python编程").first().prefetch_related("author") print(f"书籍作者:{book.author.name}") ``` 2. **反向查询**(从作者查书籍): ```python async def get_author_books(): author = await Author.filter(name="李华").first().prefetch_related("books") for book in author.books: print(f"作品:{book.title}") ``` #### 三、多对多关联查询 增加$Tag$(标签)模型演示多对多关系: ```python class Tag(models.Model): id = fields.IntField(pk=True) name = fields.CharField(max_length=30) books = fields.ManyToManyField("models.Book", related_name="tags") async def get_book_tags(): book = await Book.filter(title="Python编程").prefetch_related("tags") for tag in book.tags: print(f"标签:{tag.name}") ``` #### 四、关联过滤查询 ```python # 查询包含"算法"标签的书籍 books = await Book.filter(tags__name="算法").prefetch_related("author") ``` #### 五、性能优化建议 使用`prefetch_related`可减少数据库查询次数[^2],避免N+1查询问题: ```python authors = await Author.all().prefetch_related("books", "books__tags") ``` $$ \text{关联查询复杂度} = O(n) \text{(使用预取后)} \quad \text{vs} \quad O(n^2) \text{(未使用预取)} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值