代码之家  ›  专栏  ›  技术社区  ›  wsorenson

Django模型-如何在事实发生后按pk过滤掉重复值?

  •  6
  • wsorenson  · 技术社区  · 17 年前

    我通过进行几个查询来构建django模型对象的列表。然后,我想删除所有重复的对象(所有这些对象都是同一类型,具有自动递增的int-pk),但是我不能使用set(),因为它们不可哈希。

    有没有一种简单快捷的方法?我正在考虑用听写代替以ID为键的列表。

    6 回复  |  直到 16 年前
        1
  •  6
  •   David Berger    17 年前

    有没有一种简单快捷的方法?我正在考虑用听写代替以ID为键的列表。

    这正是我将要做的,如果您被锁定在当前的结构中进行几个查询。然后简单地 dictionary.values() 将返回您的列表。

    如果你有一点灵活性,为什么不使用 Q 物体?不是实际进行查询,而是将每个查询存储在 Q 对象,并使用按位或(“”)执行单个查询。这将实现您的目标并保存数据库命中。

    Django Q objects

        2
  •  12
  •   gerdemb    17 年前

    一般来说,如果可能的话,最好将所有查询合并为单个查询。IE.

    q = Model.objects.filter(Q(field1=f1)|Q(field2=f2))
    

    而不是

    q1 = Models.object.filter(field1=f1)
    q2 = Models.object.filter(field2=f2)
    

    如果第一个查询返回重复的模型,则使用distinct()。

    q = Model.objects.filter(Q(field1=f1)|Q(field2=f2)).distinct()
    

    如果您的查询真的无法用一个命令执行,那么您将不得不使用dict或其他答案中推荐的技术。如果您在so上发布了准确的查询,这可能会有所帮助,我们可以看看是否可以将其合并为单个查询。根据我的经验,大多数查询可以用一个查询集来完成。

        3
  •  3
  •   Jarret Hardie    17 年前

    如果添加 __hash__ 函数到模型定义,以便它返回ID(假设这不会干扰应用程序中的其他哈希行为):

    class MyModel(models.Model):
    
        def __hash__(self):
            return self.pk
    
        4
  •  0
  •   ibz    17 年前

    如果顺序无关紧要,使用听写。

        5
  •  0
  •   S.Lott    17 年前

    删除“重复”取决于您如何定义“重复”。

    如果你想让每一列(除了pk)都匹配,那就是颈部疼痛——这是很多比较。

    另一方面,如果您有一些“自然键”列(或短列集),那么您可以轻松地查询和删除这些列。

    master = MyModel.objects.get( id=theMasterKey )
    dups = MyModel.objects.filter( fld1=master.fld1, fld2=master.fld2 )
    dups.all().delete()
    

    如果您可以识别一些较短的关键字段集来进行重复识别,那么这就可以很好地工作。


    编辑

    如果模型对象尚未保存到数据库中,您可以在这些键的元组上创建字典。

    unique = {}
    ...
    key = (anObject.fld1,anObject.fld2)
    if key not in unique:
        unique[key]= anObject
    
        6
  •  0
  •   sth    16 年前

    我用这个:

    dict(zip(map(lambda x: x.pk,items),items)).values()