使用模型中"through"字段批注查询集模型



这似乎很容易,但尽管谷歌搜索了很多,我还是无法找到答案。

我有两个模型,通过第三个模型通过具有一些附加字段的多对多关系连接起来。

class User(AbstractUser):
pass
class Project(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
description = models.CharField(max_length=255, blank=True)
users = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='projects', through='UserProject')
# additional project fields
class UserProject(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
favorite = models.BooleanField(default=False)
last_used = models.DateTimeField(default=timezone.now)

我想要的是能够访问给定用户的项目以及每个项目的该用户的favoritelast_used字段。

我无法弄清楚如何在调用user.projects时使用注释或任何其他方法做到这一点。如果我直接调用 through 关系(即user.userproject_set),我可以通过调用(例如user.userproject_set.select_related('project').annotate(name='project.name'))使用单个 sql 查询从项目中添加字段,但结果查询集中的模型是 UserProjects,而不是 Projects,这不是我想要的。

编写一个 sql 查询来做我想做的事情是微不足道的(它基本上与 Django 生成的将项目字段连接到 UserProject 查询集的查询相同)。有没有办法让 Django 将字段从 through 表添加到通过多对多关系的一侧访问的查询集中的模型中?

只需使用相关名称即可访问相关对象。使用它,你应该得到Project对象:

user.projects.all()

在尝试了许多不同的选项(包括 FilterRelation)之后,我找到了一种方法,通过使用 QuerySet 的extra方法从中间表中添加我想要的字段来获取我想要的字段:

user.projects.extra(select={
'favorite': 'app_userproject.favorite',
'last_used': 'app_userproject.last_used'
})

不需要额外的 SQL 查询/数据库命中、新的连接和对where子句的更改,因为相关的连接和条件已经是查询 Django 构造的一部分,用于从多对多关系中检索子模型。这就是为什么似乎应该有一些方法可以在Django中做到这一点,而不必诉诸extra- Django威胁要弃用它。

最新更新