Django-ORM-3:orm跨表查询,子查询(基于对象的跨表查询)和联表查询(基于双下划线的跨表查询)

外键在哪里,哪里就是正向。

1、由外键所在的表去查其他表,这就是正向

2、由没有外键所在的表去查,这就是反向

书和出版社:外键设置在书表中

1、通过书表去查对应的出版社,这是正向查询
2、通过出版社表去查出版的所有书,这就是反向

正向查询按字段
    在多对多关系表中,正方向也要加all()

反向查询按表名小写.__set
    查询结果是多个时,再加上  .all()
  • 正向查询:点外键
  • 返回结果是多个,需要加 .all()
  • 反向查询:表名小写
  • 多个结果时,需要加 _set.all()
  • 两行代码实现
  • 先拿到当前表指定的数据对象
  • 通过该数据对象+.all()或_set.all()实现跨表查,拿到另一张的整张表数据

  • 正向查询:外键__字段

  • 反向查询:表名小写__字段
  • 一行代码实现
  • 通过filter拿到当前表指定的数据
  • 再通过values ,获取当前表字段和跨表字段

正向查询:点外键字段

​ 特殊:查询结果 是多个时加 .all(), (多对多关系表的正向查询要加all())

反向查询:点表名小写_set.all()

​ 特殊:查询结果只有一个时,直接点表名(一对一关系表)

多表查询

表数据,人与人的详细信息,外键设置在人表上


class Person(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    persondetail = models.OneToOneField(to='PersonDetail',on_delete=models.CASCADE,db_constraint=False)

    def __str__(self):
        return self.name

class PersonDetail(models.Model):
    id = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=13)
    address = models.CharField(max_length=100,null=True)

    def __str__(self):
        return self.phone

persondetail = models.PersonDetail.objects.get(id=1)

person = persondetail.person

person = models.Person.objects.get(id=1)

persondetail = person.persondetail
print(persondetail)

表数据:书与出版社,一对多关系

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False)

    def __str__(self):
        return self.name

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

    def __str__(self):
        return self.name

2.1、子查询的反向查询

'''
反向查询,是给没有外键的表使用
1、一对多关系表中,外键在多上,所以这种方式的反向查询,一定要加上all()
2、对于多对多关系表中,反向查询也一定要加上all()
3、对于一对一关系表中,反向查询就不需要加all()
'''

publish = models.Publish.objects.filter(id=1).first()

books = publish.book_set.all()
for book in books:
    print(book)

2.2、子查询的正向查询


book = models.Books.objects.filter(id=3).first()

publish = book.publish
print(publish)

数据准备:书和作者,是多对多的关系,是通过第三张表实现多对多关系,哪个表的字段设置了ManyToManyField的,该字段就算是外键了。

外键设置到书上了

半自动生成第三张表
class Book(models.Model):
    id = models.AutoField(primary_key=True,verbose_name='主键')
    name = models.CharField(max_length=100,verbose_name='书名')
    price = models.DecimalField(max_digits=10,decimal_places=2,verbose_name='价格')
    authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))

class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50,verbose_name='作者')
    address = models.CharField(max_length=100,verbose_name='作者地址')

class Book2Author(models.Model):
    id = models.AutoField(primary_key=True,verbose_name='书作者关系主键')
    book = models.ForeignKey(to='Book',on_delete=models.DO_NOTHING,db_constraint=False)
    author = models.ForeignKey(to='Author',on_delete=models.DO_NOTHING,db_constraint=False)
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')

    class Meta:

        unique_together=['book','author']

#查看某个作者的写过的所有书,外键在书表中
author = models.Author.objects.get(id=1)
#多对多都是:表名小写_set.all()
books = author.book_set.all()
print(books)
book = models.Book.objects.get(id=2)

authors = book.authors.all()
print(authors)

你的查询没有错误,只是少了.all() , 因为你这个查询默认是返回多条数据的,所以需要使用all()方法来拿。

1、正向查询时,通过外键跨表,返回多个数据时,要使用.all()获取。[只有多对多关系需要.all(),系统默认会拿到多个数据]

2、反向查询时,通过表名小写[_set.all()],返回多个数据时就必须加_set.all(). [在一对一关系表中,就直接表名小写就可以了]、

3、带all()的结果是列表套字典
4、不带all()的结果就是query对象了

正向查询:通过 外键__字段 获取另一张的字段数据

反向查询:通过 表名小写__字段 获取另一张的字段数据

数据准备:人和人的详细信息,一对一关系,外键在人表上。

1.1、正向查询


person = models.Person.objects.filter(id=1).values('persondetail__address','persondetail__phone','name')

print(person.first())
print(person.first().get('persondetail__address'))

1.2、反向查询


persondetail = models.PersonDetail.objects.filter(id=2).values('person__name','address','phone')

print(persondetail)

数据准备:books 和publish,多对一关系

class Books(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=20)
    publish = models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False)

    def __str__(self):
        return self.name

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

    def __str__(self):
        return self.name

1、正向查询

'''拿到聊斋书的出版社信息和聊斋书的信息'''

books = models.Books.objects.filter(name='聊斋').values('name','id','publish__name','publish__id')
print(books)

结果:格式列表套字典,vlaues决定
<QuerySet [{'name': '聊斋', 'id': 3, 'publish__name': '南京出版社', 'publish__id': 1}]>

2、反向查询

'''拿到南京出版社出版的所有书籍'''

publish = models.Publish.objects.filter(name='南京出版社').values('name','id','books__name','books__id')
print(publish)

<QuerySet [{'name': '南京出版社', 'id': 1, 'books__name': '水浒传', 'books__id': 5}, {'name': '南京出版社', 'id': 1, 'books__name': '西游记', 'books__id': 4}, {'name': '南京出版社', 'id': 1, 'books__name': '聊斋', 'books__id': 3}]>

数据准备: book和author,外键authors在book上

class Book(models.Model):
    id = models.AutoField(primary_key=True,verbose_name='主键')
    name = models.CharField(max_length=100,verbose_name='书名')
    price = models.DecimalField(max_digits=10,decimal_places=2,verbose_name='价格')
    authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))
    def __str__(self):
        return self.name

class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50,verbose_name='作者')
    address = models.CharField(max_length=100,verbose_name='作者地址')

    def __str__(self):
        return self.name

class Book2Author(models.Model):
    id = models.AutoField(primary_key=True,verbose_name='书作者关系主键')
    book = models.ForeignKey(to='Book',on_delete=models.DO_NOTHING,db_constraint=False)
    author = models.ForeignKey(to='Author',on_delete=models.DO_NOTHING,db_constraint=False)
    create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')

    class Meta:

        unique_together=['book','author']

1、正向查询


'''拿到西游记的所以作者'''
book = models.Book.objects.filter(name__startswith='西游').values('name','authors__name','price')
    print(book)

打印:
<QuerySet [{'name': '西游记', 'authors__name': 'lhz', 'price': Decimal('58.40')}, {'name': '西游记', 'authors__name': 'zzh', 'price': Decimal('58.40')}]>

    print(book.first().get('authors_name'))

2、反向查询

'''找到lhz作者的所有书籍'''

author = models.Author.objects.filter(name__startswith='lhz').values('name','book__name','book__price')

print(author)
打印:
<QuerySet [{'name': 'lhz', 'book__name': '水浒传', 'book__price': Decimal('56.40')}, {'name': 'lhz', 'book__name': '西游记', 'book__price': Decimal('58.40')}]>

1、通过filter过滤当前表数据

2、通过values或values_list 来获取指定 的字段数据 (一般使用values,结果列表套字典),拿到当前表字段或通过外键/表名小写__字段拿到跨表的字段数据。

3、正向查询,直接通过外键__字段,获取跨表的数据

4、反向查询,直接通过表名小写__字段,获取跨表的数据

5、无论正向还是反向,结果都是被列表套住的字典或元组。

Original: https://blog.csdn.net/weixin_46371752/article/details/126375988
Author: 东林牧之
Title: Django-ORM-3:orm跨表查询,子查询(基于对象的跨表查询)和联表查询(基于双下划线的跨表查询)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/737443/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球