【问题标题】:Django models filter is slow on one itemDjango模型过滤器在一项上很慢
【发布时间】:2012-03-15 10:19:41
【问题描述】:

我有一个对组模型具有 FK 的项目模型。组有名称和另外两个字段:(bool) is_private 表示该组是否为私有,FK 到 django.auth.models.Group 表示该项目组可见的组成员身份。

有 100 个项目,不到 1 秒就被愉快地获取了:

def project_list(request):
    parameters = {field_name: value for field_name, value in request.GET.items() if value and field_name in project._meta.get_all_field_names()}
    all_projects = project.objects.select_related().filter(**parameters)
    return  all_projects

只有一个项目有一个私人组,一旦我添加隐私检查,获取它需要超过 4 秒的时间:

def project_list(request):
    parameters = {field_name: value for field_name, value in request.GET.items() if value and field_name in project._meta.get_all_field_names()}
    all_projects = project.objects.select_related().filter(**parameters)
    for p in all_projects.filter(group__is_private = True):
        if not request.user.groups.filter(name = p.group.private_group.name).exists():
        all_projects = all_projects.exclude(id=p.id)
    return  all_projects

有没有办法重做以减少时间?

【问题讨论】:

    标签: django performance django-models django-queryset


    【解决方案1】:

    在下面的代码中,您在每次迭代中都获取单个 group,因此您会进行大量数据库查询,这会减慢速度:

    all_projects = project.objects.select_related().filter(**parameters)
    for p in all_projects.filter(group__is_private = True):
        if not request.user.groups.filter(name = p.group.private_group):
    

    如果您想获取没有私有组的项目或仅当用户在该组中时才使用私有组,则使用:

    from django.db.models import Q
    
    def project_list(request):
        parameters = {field_name: value for field_name, value in request.GET.items() if value and field_name in project._meta.get_all_field_names()}
    
        group_ids = request.user.groups.values_list('id', flat=True)
        all_projects = project.objects.select_related().filter(**parameters)
        all_projects = all_projects.filter(Q(group__is_private=False) | Q(group__is_private=True, group_id__in=group_ids))
        return  all_projects
    

    【讨论】:

    • 并不是我只想选择具有私有组的项目 - 我想选择所有项目,但如果有具有私有组的项目,我希望它们仅在请求用户是其成员时才在列表中project_group_(FK)_private_group
    • 我修改了代码以反映这一点。我使用Q query 过滤“(组非私有)或(组私有且用户拥有该组)”
    • 是的,以防万一其他人使用此解决方案 - 需要添加“| group = None”并将 droup_id 替换为 private_group__id
    猜你喜欢
    • 2016-10-22
    • 2012-03-13
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多