Django的ORM中的反向引用和反向查询

Django中的多对一、一对一、多对多关系

在Django中,可以使用models.ForeignKeymodels.OnetToOneFieldmodels.ManyToManyField来分别实现多对一、一对一和多对多的表关系,例如下面的例子:

多对一关系

class User(models.Model):
    username = models.CharField(max_length=20)
    password = models.CharField(max_length=100)

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey("User",on_delete=models.CASCADE)

在给Article对象指定author时,很显然可以直接使用属性的方式来完成。
那么如果想要获取某个author所有的文章Article,可以通过article_set来实现,这就叫反向引用,虽然我们没有在代码中显式地写这这个变量,但是Django会帮我们实现这个功能,命名格式就是classname_set,也就是声明外键的表的小写名字加上_set,因为是多的那一方,所以使用set来命名表示这是一个集合。

一对一关系

class FrontUser(models.Model):
    username = models.CharField(max_length=200)

class UserExtension(models.Model):
    school = models.CharField(max_length=100)
    user = models.OneToOneField("FrontUser",on_delete=models.CASCADE)

在一对一关系中,反向引用的写法稍有不同,可以通过userextension来访问UserExtension对象

user = FrontUser.objects.first()
print(user.userextension)

这也可以理解,因为是一对一的关系,所以是一个单数,也就不需要加_set了。

多对多关系

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    tags = models.ManyToManyField("Tag",related_name="articles")

class Tag(models.Model):
    name = models.CharField(max_length=50)

在数据库层面,Django会自动为这种多对多的关系建立一个中间表,不需要我们人为地去写。这个中间表分别定义了两个外键,引用到articletag两张表的主键。
因为这里引用方也是多的那一方,所以在进行反向引用时,也需要加_set

反向引用和反向查询

反向引用

反向引用就是上面说的,被引用的对象通过属性的方式访问引用的对象,Django默认的访问方式就是多方加_set的格式,但是我们也可以自定义访问的方式,也就是在多对多的demo中使用的related_name="articles",增加了这个参数之后,在tag中访问article对象实际的写法应该是:

tag = Tag.objects.first()
print(tag.articles)

反向查询

反向查询是使用filter的方式进行数据库查询使用的名称,它和反向引用的默认名称不太一样,需要注意。
例如我们下面的例子:

class Category(models.Model):
    name = models.CharField(max_length=100)

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    cateogry = models.ForeignKey("Category",on_delete=models.CASCADE,related_query_name='articles')


categories = Category.objects.filter(article__id__in=[1,2,3])

显然这里是多对一的关系,我们使用category进行反向查询,但是我们使用的是article而不是article_set,这就是Django默认名称定义的格式不同,当然也可以使用和反向引用类似的related_query_name='articles'的方式定义我们自己喜欢的名称。

你可能感兴趣的:(Django)