我有一个模型,Entry.
特别值得注意的是它的addTags
函数,它将标记添加到Entry
的实例并保存。以下是该类的完整代码:
class Entry(models.Model):
title = models.CharField(max_length=80)
author = models.ForeignKey(User)
pubdate = models.DateTimeField()
tags = models.ManyToManyField(Tag)
text = models.TextField()
def getAllTags(self):
'''
Returns all tags applied to a given entry
'''
return self.tags.all()
def addTag(self, tagName):
'''
Add a tag to an entry. If tag does not exist, create it. If tag has
already been added, do nothing.
'''
try:
tag = Tag.objects.get(name=tagName)
return tag
except Tag.DoesNotExist:
tag = self.tags.create(name=tagName)
self.save()
return tag
奇怪的是,当我使用以下代码测试addTag函数时(之前创建的entry1是一个有效的Entry对象):
tag1 = entry1.addTag("testtag2")
tag2 = entry1.addTag("testtag2")
tag3 = entry1.addTag("testtag3")
tagList = [tag1, tag2, tag3]
for listTag, objTag in zip(tagList, entry1.tags.all()):
print "%s: %s" % (listTag, objTag)
self.assertEqual(entry1.tags.all(), tagList)
我收到以下断言错误:
AssertionError: [<Tag: testtag>, <Tag: testtag2>, <Tag: testtag3>] != [<Tag: testtag>, <Tag: testtag2>, <Tag: testtag3>]
然而,上面代码中的print语句给出了以下内容:
testtag: testtag
testtag2: testtag2
testtag3: testtag3
表示已按预期创建标记。似乎每个标记对象的不同内存位置都已创建,但我不知道这是怎么回事。思考?
答案 0 :(得分:2)
self.assertEqual(list(entry1.tags.all()), tagList)
entry1.tags.all()是一个不覆盖__eq__方法的查询集,因此通过它的id(内存位置)与其他对象进行比较。如果要将它返回的对象与tagList中的对象进行比较,则必须首先通过调用list来评估查询集。
列表中的条目实例(entry1.tags.all())与tagList中的实例不同。这并不会改变两个列表相同,因为Entry实例确实有一个重写的__eq__方法,并通过它们的pk进行比较。
编辑:
将QuerySet与列表进行比较时
entry1.tags.all() == tagList
您没有比较它返回的实例,因为Queryset没有覆盖__eq__方法,因此无法与列表进行比较。
然而,可以比较两个列表。列表中的所有实例都是成对比较的,因为它们的__eq__提供了除id-comparison之外的其他方法(它测试pk相等性),它们进行了比较。
答案 1 :(得分:0)
尝试重构代码:
class Entry(models.Model):
title = models.CharField(max_length=80)
author = models.ForeignKey(User)
pubdate = models.DateTimeField()
tags = models.ManyToManyField(Tag)
text = models.TextField()
def getAllTags(self):
'''
Returns all tags applied to a given entry
'''
return self.tags.all()
def addTag(self, tagName):
'''
Add a tag to an entry. If tag does not exist, create it. If tag has
already been added, do nothing.
'''
tag = Tag.objects.get_or_create(name=tagName)
self.tags.add(tag)
self.save()
此外,在测试中,您必须比较两个列表:
self.assertEqual(list(entry1.tags.all()), tagList)