使用Django ORM进行表连接
我正在学习Django的ORM(对象关系映射),但对表连接的概念有点困惑。
假设我有下面三个模型,简化了以便阅读。“User”是Django自带的用户模型,“AppUser”是一个对应的模型,用来存储额外的个人资料信息,比如邮政编码,而“Group”是用户的集合(注意,这个组和认证组没有关系)。每个AppUser和每个User之间是一对一的关系。同时,每个AppUser也指向它所属的Group(这个Group可能是空的)。
我的任务是:给定一个group_id,生成所有成员的邮箱列表。
我知道可以通过 .appuser_set.all()
从Group向回查找到AppUser,但我不知道怎么进一步获取相关的User及其邮箱,而不想通过遍历的方式,这样会对数据库造成很大的负担,像这样:
appUser = AppUser.objects.get(user_id=request.user.id)
group = appUser.group
appUsers = group.appuser_set.all()
emails = []
for x in appUsers:
emails.append(x.user.email)
另外,我可以写一个原始的SQL连接来实现这个功能,但我怀疑Django的ORM也能做到。请问,正确且最有效的方法是什么呢?
模型:
class User(Model):
id = IntegerField()
username = CharField()
email = CharField()
class Meta:
db_table = "auth_user"
class AppUser(Model):
user = OneToOneField(User, primary_key=True)
group = ForeignKey('Group', null=True, on_delete=SET_NULL)
zip = CharField()
class Meta:
db_table = "app_users"
class Group(Model):
creator = ForeignKey(AppUser, related_name='+')
created = DateTimeField()
name = CharField()
class Meta:
db_table = "groups"
1 个回答
2
诀窍是始终从你想要获取的模型开始。在这个例子中,你想获取的是电子邮件,而电子邮件是用户模型上的一个字段。所以,从用户模型开始,然后用双下划线的语法来跟踪到组的关系:
users = User.objects.filter(appuser__group_id=group_id)
在这种情况下,其实你只需要一个 JOIN,因为 group_id
是 AppUser 自身的一个字段(它是 group
外键在数据库中的实际字段)。如果你有组名,那就需要两个 JOIN:
users = User.objects.filter(appuser__group__name=group_name)