Python Django select与条件间接相关

Python Django select与条件间接相关,python,django,django-queryset,Python,Django,Django Queryset,在我的项目中,我有用户,他们可以扮演某种角色。但是,这些角色受日期范围的限制,即用户可以在2020年1月1日至2020年2月2日期间具有管理员角色,并且可以在2020年2月2日至2020年3月3日期间具有非特权用户角色 我需要能够返回具有当前角色的用户列表,并且我希望能够只对数据库进行一次查询。然而,我不知道该怎么做 以下是我的模型: class User(models.Model): ... class Role(models.Model): name = models.Ch

在我的项目中,我有
用户
,他们可以扮演某种角色。但是,这些角色受日期范围的限制,即用户可以在2020年1月1日至2020年2月2日期间具有管理员角色,并且可以在2020年2月2日至2020年3月3日期间具有非特权用户角色

我需要能够返回具有当前角色的用户列表,并且我希望能够只对数据库进行一次查询。然而,我不知道该怎么做

以下是我的模型:

class User(models.Model):
    ...

class Role(models.Model):
    name = models.CharField(...)

class UserRoleQuerySet(models.QuerySet):
    def current():
        return self.filter(period__contains=date.today())

class UserRoles(models.Model):
    user = models.ForeignKey(User, related_name='roles')
    role = models.ForeignKey(Role)
    period = DateTimeRangeField()

    objects = UserRoleQuerySet.as_manager()
我需要一个查询集,该查询集上调用了
预回迁相关
选择相关
注释
方法,这样当我执行下面的代码时,我就不会得到额外的数据库访问:

users = User.objects.(some_magic_here).all()
for user in users:
    print(user.role)

UPD:更具体地说,如果我不做任何注释、预取或选择_相关,我将得到所有(当前)用户角色的打印输出。但是,每次迭代都会命中db以选择当前角色。我想要的是相同的打印输出,但是没有额外的到db的往返来获得一组对象,您将需要
预回迁相关的
,尽管您不能在预回迁后更改(过滤)查询,因为Django将无法进行连接。因此,在Django进行预取时,您需要提供过滤器:

users = Users.objects.prefetch_related(
    Prefetch(
        'roles',
        queryset=(
            UserRoles.objects
                .filter(period__contains=date.today())
                .select_related('role')
        )
    )
)
当您在
用户中迭代时,如果更改查询,每次迭代都会对数据库进行一次额外的点击,因此不要执行以下操作:

for user in users:
    print(user.roles.first().role)
您需要执行以下操作以避免进一步查询数据库,因为您知道
user.roles.all()
始终只会给出一个结果:

for user in users:
    for user_role in user.roles.all():
        print(user_role.role)

给出你想要的结果want@kyore添加了更新。我现在看到的是这样的:.extra(select={'monthly_-fee':'mobile_-subscription.monthly_-fee'})据我所知,您希望queryset的每个项目都包含用户当前的角色名称?@kyore我想要整个相关的角色对象,但我认为一个查询也不可能包含该名称
User.objects.prefetch\u related('roles\uu role')
被点击3次,所有其他访问都是免费的谢谢您的回复。但在迭代过程中,每个用户仍会访问数据库一次。您能看到它正在查询什么吗?在预回迁中的queryset上用“select_related”更新了回复。现在它起作用了。(谢谢)