6

我通过进行几个查询来构建 Django 模型对象的列表。然后我想删除任何重复项,(所有这些对象的类型都与 auto_increment int PK 相同),但我不能使用 set() 因为它们不可散列。

有没有一种快速简便的方法来做到这一点?我正在考虑使用 dict 而不是以 id 为键的列表。

4

6 回答 6

13

一般来说,如果可能的话,最好将所有查询合并到一个查询中。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 上发布确切的查询可能会有所帮助,我们可以看看是否可以组合成一个查询。根据我的经验,大多数查询都可以使用单个查询集完成。

于 2009-04-14T13:40:00.330 回答
6

有没有一种快速简便的方法来做到这一点?我正在考虑使用 dict 而不是以 id 为键的列表。

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

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

Django Q 对象

于 2009-04-13T16:27:26.083 回答
2

如果您将__hash__函数添加到模型定义中,则可以使用一个集合,以便它返回 id(假设这不会干扰您在应用程序中可能具有的其他哈希行为):

class MyModel(models.Model):

    def __hash__(self):
        return self.pk
于 2009-04-13T16:58:21.313 回答
0

如果顺序无关紧要,请使用字典。

于 2009-04-13T16:24:46.120 回答
0

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

如果您希望每列(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
于 2009-04-13T17:44:12.297 回答
0

我用这个:

dict(zip(map(lambda x: x.pk,items),items)).values()
于 2010-02-22T19:08:06.483 回答