django orm:检查obj是否在queryset中

时间:2014-08-20 08:02:24

标签: django orm contains

如何检查obj是否在查询集中?

我试过了:

self.assertIn(obj, list(MyModel.objects.filter(...))

但它在我的情况下不起作用。

AssertionError: <MyModel 137 'unclassified'> not found in 
[<MyModel 1676 'foo'>, ..., <MyModel 137 'unclassified'>, ...]

我不明白,因为它在列表中。

5 个答案:

答案 0 :(得分:3)

怎么样

self.assertTrue(MyModel.filter(...).filter(pk=obj.pk).exists())

答案 1 :(得分:1)

首先,它应该是MyModel.objects.filter(...)。如果你省略.objects,你应该会得到一个不同的错误,所以我假设你确实包含了它,但在问题中忘了它。

如果obj实际上在QuerySet返回,那么你所做的应该是有效的,因为Django模型实例提供了一个相等的比较器,它比较了类型和主键。 list()周围不需要QuerySet,但如果您使用它,它仍然可以使用。

来自Django 1.5 source

def __eq__(self, other):
    return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()

如果它仍然不起作用,可能有几个原因:

  1. 类型不匹配。在这种情况下,即使对象pk存在于QuerySet的对象pks中也没有关系。 (你无法将苹果与橙子进行比较)
  2. 数据库中没有这样的对象(即它还没有被保存)
  3. 类型匹配但对象不在QuerySet中(即已过滤掉)
  4. 你覆盖了__eq__方法并做了一些奇怪的事情。或者您使用一些自定义过滤器覆盖默认管理器.objects。这种情况超出了这个答案的范围,如果你这样做,你应该知道如何解决它。
  5. 为了帮助您诊断出是哪种情况,请尝试以下方法:

    self.assertTrue(isinstance(obj, MyModel))
    # 1. If it fails here, your object is an incorrect type
    
    # Warning: the following tests can be very slow if you have a lot of data
    
    self.assertIn(obj.pk, MyModel.objects.values_list('pk', flat=True))
    # 2. If it fails here, the object doesn't exist in the database
    
    self.assertIn(obj.pk, MyModel.objects.filter(...).values_list('pk', flat=True))
    # 3. If it fails here, the object did not pass your filter conditions.
    
    self.assertIn(obj, MyModel.objects.filter(...))
    # 4. If it fails here, you probably messed with the Django ORM internals. Tsk tsk.
    

答案 2 :(得分:0)

请注意.all()

queryset_result = MyModel.filter(...).all()

if obj in  queryset_result:
    //obj is in the queryset

答案 3 :(得分:0)

“in”失败,因为对象实际上并不相等,因为默认情况下equ是对象标识。如果您希望“在”中工作,则必须在模型上相应地实施__eq__

如果您不想这样做,可以通过比较pk进行检查,如此

self.assertIn(obj.pk, [o.pk for o in MyModel.filter(...)])

答案 4 :(得分:0)

我认为这是非常简单的方法来查找queryset中存在的对象。

第一个例子:

obj_list = MyModel.filter(...)
if obj in obj_list:
    print "obj in queryset"
else:
    print "not in queryset"

第二个例子:

obj_list = MyModel.filter(...)

try:
   obj_list.get(pk=obj.id)
except:
   # If try get success obj is present in query set else your this except get executed.