简体   繁体   English

使用Django ORM进行表联接

[英]Table join using the Django ORM

I'm trying to figure out the Django ORM and I'm getting a little confused on the equivalent of a table join. 我试图弄清楚Django ORM,而在等效于表联接的情况下我有点困惑。

Assume I have the three models below, abbreviated for readability. 假设我有以下三个模型,为便于阅读而缩写。 "User" is the out-of-the-box Django user model, "AppUser" is a corresponding model for storing additional profile info like zip code, and "Group" is a collection of users (note that this group has nothing to do with authentication groups). “用户”是开箱即用的Django用户模型,“ AppUser”是用于存储其他个人资料信息(例如邮政编码)的对应模型,“组”是用户的集合(请注意,该组无关与身份验证组)。 Each AppUser has a one-to-one relationship with each User. 每个AppUser与每个User都具有一对一关系。 Similarly, each AppUser also points to the Group of which that user is member (which could be None). 同样,每个AppUser也指向该用户所属的组(可以为None)。

My task: given a group_id, generate a list of all the member emails. 我的任务:给定一个group_id,生成所有成员电子邮件的列表。

I know that I can "traverse backward one-level" from Group to AppUser using .appuser_set.all() but I don't know how to go further to fetch the related User and its email without iterating through and doing it in a very DB heavy way like this: 我知道我可以使用.appuser_set.all()从组“向后遍历”到AppUser,但是我不知道如何进一步获取相关的用户及其电子邮件,而无需进行反复遍历和完成DB的重载方式是这样的:

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) 

Alternatively I could write a raw SQL join to do it but suspect the Django ORM is capable. 另外,我可以编写一个原始SQL连接来执行此操作,但怀疑Django ORM是否可以。 What's the proper and most efficient way to do this? 什么是正确且最有效的方法?

Models: 楷模:

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"

The trick is to always start from the model you actually want to fetch. 诀窍是始终从您实际要获取的模型开始。 In this case, you want to fetch emails, which is a field on the User model. 在这种情况下,您要获取电子邮件,这是用户模型上的一个字段。 So, start with that model, and use the double-underscore syntax to follow the relationships to Group: 因此,从该模型开始,并使用双下划线语法遵循与Group的关系:

users = User.objects.filter(appuser__group_id=group_id)

In this case, you actually only need a single JOIN, because group_id is a field on AppUser itself (it's the underlying db field for the group ForeignKey). 在这种情况下,您实际上只需要一个JOIN,因为group_id是AppUser本身的字段(这是group ForeignKey的基础db字段)。 If you had the group name, you would need two joins: 如果您具有组名,则需要两个联接:

users = User.objects.filter(appuser__group__name=group_name)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM