【问题标题】:Removing duplicate objects within a Django QuerySet删除 Django QuerySet 中的重复对象
【发布时间】:2021-05-17 19:36:10
【问题描述】:

这个问题我已经看过几次了,但我真的找不到对我的问题有很大意义的解决方案。

>>> query = ['software', 'engineer']
>>> hits = []
>>> for q in query:
...    x = Vacancy.objects.filter(Q(job_title__icontains=q))
...    hits.append(x)
...
>>> hits
[<QuerySet [<Vacancy: 6 Software Engineer>]>, <QuerySet [<Vacancy: 6 Software Engineer>]>]

如何清理命中 QuerySet 使其没有任何重复项?

我尝试了以下方法,但没有成功:

>>> hits = list(dict.fromkeys(hits))
>>> hits
[<QuerySet [<Vacancy: 6 Software Engineer>]>, <QuerySet [<Vacancy: 6 Software Engineer>]>]

【问题讨论】:

    标签: python django duplicates django-queryset


    【解决方案1】:

    @sarchi-xo - Vacancy.objects.filter(Q(job_title__icontains=q)).distinct()。这行得通吗?

    只是为了更清楚。这是 distinct() 在查询集上运行良好的快照。不知道为什么您会收到“列表对象没有不同的属性”

    【讨论】:

    • 他没有存储重复项,他正在查询他的单词列表中的每个单词并将结果附加到命中列表
    • 是的,正如@iklinac 所说。我也尝试过 .distinct() ,但出现属性错误。 AttributeError: 'list' object has no attribute 'distinct'.
    • @sarchi-xo- 在查询集上尝试 distinct。它不会抛出错误。 x = Vacancy.objects.filter(Q(job_title__icontains=q)).distinct()
    • @SDRJ 你刚刚重复了同样的事情,我已经告诉你我试过了,但没有用?!
    • @sarchi-xo- 我什至自己测试过。在快照中添加。不确定您收到错误的原因。
    【解决方案2】:

    您可以在过滤器中链接 Q 对象,而不是生成对数据库的单个查询

    from functools import reduce
    from operator import or_
    
    words = ['software', 'engineer']
    or_filter = reduce(or_, (Q(job_title__icontains=word) for word in words))
    
    
    Vacancy.objects.filter(or_filter)
    

    或者您可以在添加对象之前检查您是否已经在列表中拥有该对象,例如保留一组对象 ID

    【讨论】:

    • 我通过名称错误导入了 reduce,但现在我收到另一个名称错误:NameError: name 'or_' is not defined
    • or_ 来自运营商模块docs.python.org/3/library/operator.html。我添加了导入语句
    【解决方案3】:

    我解决了!! 与其使用 filter,不如使用 get,而不是列表中的每个项目都是一个 QuerySet,每个项目都是一个 Vacancy 对象并且很容易访问。

    >>> for q in query:
    ...    x = Vacancy.objects.get(Q(job_title__icontains=q))
    ...    hits.append(x)
    ...
    >>> hits
    [<Vacancy: 6 Software Engineer>, <Vacancy: 6 Software Engineer>]
    >>> hits = list(dict.fromkeys(hits))
    >>> hits
    [<Vacancy: 6 Software Engineer>]
    

    【讨论】:

    • 如果您在该模型中有大量数据,并且带有 job_title =' 的查询集软件工程师返回假设十亿行您要将所有这些数据存储在内存中的命中列表中,会发生什么?
    • 应通过使用内置过滤器或编写自定义 SQL 将尽可能多的查询集操作卸载到数据库端。数据库速度更快,专为这种情况而构建。
    • @SDRJ 我编辑了我的答案,因为我意识到没有必要专门访问 job_title。
    • @sarchi-xo-hits.append(x)。如果您的应用程序增长并且您在数据库中有大量数据并且您通过将所有这些数据存储在列表中来将所有这些数据附加到内存中,请考虑这个列表。我不知道您正在研究的确切用例,但从长远来看可能需要考虑。
    【解决方案4】:

    隐蔽设置,然后再次列出

    hits=list(set(hits))
    >>> hits
    [<Vacancy: 6 Software Engineer>]
    

    【讨论】:

      猜你喜欢
      • 2011-07-25
      • 2013-05-04
      • 2020-11-04
      • 1970-01-01
      • 2019-09-22
      • 2020-10-01
      • 2011-02-16
      • 1970-01-01
      • 2020-10-31
      相关资源
      最近更新 更多