django跨表查询

https://blog.csdn.net/moshanghuali/article/details/103849558

一. 基于对象的跨表查询方式,常用的是符号 .

基于对象的跨表查询也分正向查询和反向查询。

由主表查从表就是反向,由从表查主表就是正向。一般来说外建放在那个表中,哪个表就是从表。有点绕

从有外键的表开始查,就是正向查询

例如:

class UserInfo(models.Model):
    username=models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    address = models.CharField(max_length=32)

class UserDetail(models.Model):
    boyfiend_name = models.CharField(max_length=32)
    phonenum = models.CharField(max_length = 11)
    user = models.ForeignKey(UserInfo,related_ name='uuu')

注意:

无论是正向查询还是反向查询,首先记住这种查询方式是基于对象的查询。

get()或者first(),last()等获得的是单个对象。而filter返回的是封装好的列表

1. 正向查询:
UserDetail(从表) --> UserInfo (主表) 

UserDetail.objects.get(id=1).user.all()
UserDetail.objects.get(id=1).user.username
UserDetail.objects.get(id=1).user.pwd
2. 反向查询:
UserInfo (主表) --> UserDetail(从表)

UserInfo.objects.get(id=1).uuu.all()
#这里related_name == 表名_set,如果user外建没设置related_name的话
UserInfo.objects.get(id=1).userdetail_set.all()

# 注意反向操作的时候,由于查询出的可能是一个QuerySet。因此不可以在最后直接点.字段名。
UserInfo.objects.get(id=1).uuu.all()[0].phonenum
UserInfo.objects.filter(id=1).first().uuu.all()[0].phonenum

二. 基于双下划线的跨表查询

基于双下划线的跨表查询也分为正向查询和反向查询。

1.正向查询:查询条件字段或者查询字段在主表中。由从表查主表。正向查询时用双下划线方式为:外键字段__关联表的字段
# 查询条件字段在主表中,最终查询字段值在从表中。
UserDetail.objects.filter(user__pwd=123).values()

# 查询字段值在主表中,查询条件字段在从表中。
UserDetail.objects.filter(phonenum=110).values('user__pwd') 
2. 反向查询:查询条件字段或者查询字段值在从表中,由主表查从表。反向查询时用双下划线方式为:表名__字段
# 查询条件字段在从表中。
UserInfo.objects.filter(uuu__phonenum=110).values()

# 查询字段值在从表中。
UserInfo.objects.filter(username='xiao').values('uuu__phonenum')
class Department(models.Model):
 title = models.CharField(verbose_name='名称',max_length=32)
 
class UserInfo(models.Model):
 depart=models.ForeignKey(verbose_name='部门',to='Department',related_query_name="u")
 user = models.CharField(verbose_name='员工',max_length=32)
 pwd = models.CharField(verbose_name='密码', max_length=32)

正向查询

user_object = UserInfo.objects.get(id=1)
user_object.depart

反向查询,related_query_name相当于从表的别名

depart_object = Department.objects.get(id=9)
depart_object.u_set.all()

当related_query_name和related_name同时出现时,related_query_name会覆盖related_name,你再使用related_name会报错。当related_name出现时,而related_query_name未出现。你必须使用related_name,此时在使用表名的话会报错。

在反向查询时,在没有设置related_name的时候,基于双下划线只需使用表名,而基于对象的查询方式需要使用表名_set

class Category(models.Model):
    """文章分类表"""
    name = models.CharField(max_length=100)

class Article(models.Model):
    """文章表"""
    title = models.CharField(max_length=100,null=True)
    category = models.ForeignKey("Category",on_delete=models.CASCADE)

比如想要获取文章标题中包含"hello"的所有的分类。那么可以通过以下代码来实现:

categories = Category.object.filter(article__title__contains("hello"))
posted @ 2022-10-25 16:44  坚强的小蚂蚁  阅读(325)  评论(0编辑  收藏  举报