0

我有一个模型,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

表示标签已按预期创建。似乎每个标签对象的不同内存位置都已创建,但我不明白这是怎么回事。想法?

4

2 回答 2

2
self.assertEqual(list(entry1.tags.all()), tagList)

entry1.tags.all() 是一个不覆盖 __eq__ 方法的查询集,因此通过它的 id(内存位置)与其他对象进行比较。如果要将它返回的对象与 tagList 中的对象进行比较,则必须首先通过调用 list 来评估查询集。

list(entry1.tags.all()) 中的 Entry 实例与 tagList 中的不同。这不会改变两个列表相等,因为 Entry 实例确实有一个被覆盖的 __eq__ 方法并通过它们的 pk 进行比较。

编辑:

将 QuerySet 与列表进行比较时

entry1.tags.all() == tagList

您没有比较它返回的实例,因为 Queryset 没有覆盖 __eq__ 方法,因此无法与列表进行比较。

但是可以比较两个列表。列表中的所有实例都是成对比较的,因为它们的 __eq__ 提供了除 id-comparison 之外的方法(它测试 pk 相等性),它们比较相同。

于 2013-04-17T19:49:36.597 回答
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)
于 2013-04-17T19:35:53.347 回答