在我的项目中,我有Users,他们可以扮演一定的角色。但是,角色受日期范围的限制,即用户可以在01.01.2020至02.02.2020之间具有管理角色,在02.02.2020至03.03.2020之间具有非特权用户角色。
我需要能够返回具有当前角色的用户列表,并且我希望能够只对数据库进行一次查询。但是,我不知道该怎么做。
以下是我的模特:
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()我需要一个带有调用它的prefetch_related、select_related或annotate方法的查询集,这样当我执行下面这样的代码时,就不会得到额外的数据库访问:
users = User.objects.(some_magic_here).all()
for user in users:
print(user.role)UPD:更具体地说,如果我不执行任何注释、预取或select_related,我将得到所有(当前)用户角色的打印输出。但是,每次迭代都将访问db以选择当前角色。我想要的是同样的打印输出,但不需要额外的往返到db。
发布于 2020-03-12 17:15:34
要获得一组对象,您将需要prefetch_related,尽管您不能在预取之后更改(筛选)查询,因为Django将无法完成连接。因此,在Django进行预取时,需要提供过滤器:
users = Users.objects.prefetch_related(
Prefetch(
'roles',
queryset=(
UserRoles.objects
.filter(period__contains=date.today())
.select_related('role')
)
)
)当您在users中迭代时,同样地,如果您更改了查询,那么每次迭代都会对数据库造成额外的打击,所以没有执行以下操作:
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)https://stackoverflow.com/questions/60656006
复制相似问题