1

我只是想知道,我有以下两个伪相关查询:

organisation = Organisation.objects.get(pk=org_id)
employees = Employee.objects.filter(organisation=organisation).filter(is_active=True)

每个Employee都有一个 ForeignKey 关系Organisation

我想知道在本地 Django ORM 的一个查询中是否可以利用任何东西来执行上述操作?

此外,将:

employees = Employee.objects.filter(organisation__id=organisation.id).filter(is_active=True)

是一种更快的获取方式employees吗?


对于威廉的参考,employees然后用作:

# Before constructing **parameters, it is neccessary to filter out any supurfluous key, value pair that do not correspond to model attributes:

if len(request.GET.getlist('gender[]')) > 0:
    parameters['gender__in'] = request.GET.getlist('gender[]')
    employees = employees.filter(**parameters)

if len(request.GET.getlist('age_group[]')) > 0:
    parameters['age_group__in'] = request.GET.getlist('age_group[]')
    employees = employees.filter(**parameters)

results = SurveyResult.objects.filter(
    user__in=employees,
    created_date__range=date_range,
).annotate(
    date=TruncDate('created_date'),
).values(
    'survey',
    'date',
).annotate(
    score=Sum('normalized_score'),
    participants=Count('user'),
).order_by(
    'survey',
    'date',
)

我省略了这一点,因为这似乎对我最初的目标来说是不必要的复杂化。

4

2 回答 2

1

此外,将:

employees = Employee.objects.filter(organisation__id=organisation.id).filter(is_active=True)

是一种更快的获取方式employees吗?

不,或者可能只是勉强,因为本质上这就是 Django ORM 自己会做的事情:它会简单地获取主键,organisation然后像你描述的那样进行查询。

如果你不需要它organisation本身,你可以查询:

employees = Employee.objects.filter(organisation_id=org_pk, is_active=True)

此外,您可以例如在组织上执行.select_related(..)[Django-doc],以在与员工相同的查询中加载数据organisation,尽管减少了一个额外的查询,但通常不会产生太大的影响。如果 iut 导致N+1 个查询,则性能更成问题。

例如,我们可以通过获取员工来“搭载”获取Organisation详细信息,例如:

employees = list(
    Employee.objects.select_related('organization').filter(
        organisation_id=org_pk, is_active=True
    )
)
if employees:  # at least one employee
    organization = employees[0].organization

但无论如何,如前所述,一两个查询之间的差异并没有那么大。如果您有N+1 个查询,这通常是一个更大的问题。有点遗憾的是,Django/Python 似乎没有等效的Haxl [GitHub],无法通过代数分析快速检索(远程)资源。

Employee如果您对servey结果感兴趣,您可以查询:

results = SurveyResult.objects.filter(
    user__organization_id=org_pk,
    created_date__range=date_range,
).annotate(
    date=TruncDate('created_date'),
).values(
    'survey',
    'date',
).annotate(
    score=Sum('normalized_score'),
    participants=Count('user'),
).order_by(
    'survey',
    'date',
)

因此,如果您仍然不需要这些,则可以省略对 s 的单独查询。Employee

您还可以将过滤器添加到查询中,例如:

emp_filter = {}
genders = request.GET.getlist('gender[]')
if genders:
    emp_filter['user__gender__in'] = genders

age_groups = request.GET.getlist('age_group[]')
if age_groups:
    emp_filter['user__age_group__in'] = age_groups

results = SurveyResult.objects.filter(
    user__organization_id=org_pk,
    created_date__range=date_range,
    **emp_filter
).annotate(
    date=TruncDate('created_date'),
).values(
    'survey',
    'date',
).annotate(
    score=Sum('normalized_score'),
    participants=Count('user'),
).order_by(
    'survey',
    'date',
)
于 2019-08-16T08:44:18.130 回答
1

如果您在组织和员工之间有外键关系,那么您可以使用select_related获取员工,如下所示:

employees = Employee.objects.selected_related('organisation').filter(is_active=True)

或者

organisation = Organisation.objects.get(pk=org_id)
employees =organisation.employee_set.all() #your_employee_model_name_set.all
于 2019-08-16T08:50:58.357 回答