python - 使用 Django ORM 进行表连接

标签 python django orm model

我正在尝试弄清楚 Django ORM,但我对表连接的等价物感到有点困惑。

假设我有以下三个模型,为了便于阅读而进行了缩写。 “User”是开箱即用的 Django 用户模型,“AppUser”是用于存储附加个人资料信息(如邮政编码)的相应模型,“Group”是用户的集合(请注意,该组与任何其他用户无关)与身份验证组)。每个 AppUser 与每个 User 都具有一对一的关系。同样,每个 AppUser 也指向该用户所属的组(可以是 None)。

我的任务:给定一个 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"

最佳答案

诀窍是始终从您实际想要获取的模型开始。在本例中,您想要获取电子邮件,这是用户模型上的一个字段。因此,从该模型开始,并使用双下划线语法来遵循与 Group 的关系:

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

在这种情况下,您实际上只需要一个 JOIN,因为 group_id 是 AppUser 本身的一个字段(它是 groupForeignKey 的基础数据库字段)。如果您有组名称,则需要两次加入:

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

关于python - 使用 Django ORM 进行表连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23432326/

相关文章:

python - C++ 中的通用异常处理

python - DeprecationWarning : firefox_binary has been deprecated, 请使用 Selenium Python 中的参数 firefox_binary 传入 Service 对象

django - 无法加载 Boto3 的 S3 绑定(bind)

java - 在 Derby 和 Hsqldb 中转义表名和字段名的问题

django - 在 Django 中使用 F() 和 timedelta 进行查询

java - spring bean 错误

python - 获取纳秒级精度的文件修改时间

python - Python中的Excel复制粘贴方式

django - 如何让 Django View 返回表单错误

python - django模型默认=""和 "This field cannot be blank"