Django:assertEquals 与 QuerySet 在视觉上相等的结果
Django: assertEquals with visually equal result with QuerySet
任何人都可以解释为什么它们具有相同的值,但不比较相等吗?很难理解这一点。使它们成为 "equal" 的最佳方法是什么?
使用 ipdb 检查:
ipdb> expected_value
{'author': 'john', 'id': 1, 'title': 'Yesterday', 'body': 'All my troubles seemed so far away', 'tags': <QuerySet ['Music', 'Lyrics']>}
ipdb> response
{'author': 'john', 'id': 1, 'title': 'Yesterday', 'body': 'All my troubles seemed so far away', 'tags': <QuerySet ['Music', 'Lyrics']>}
代码段:
class TestPost(TestCase):
def test_serialize(self):
user = User.objects.create(username="john", password="12345678", email="john@exemplo.com")
tag1 = Tag.objects.create(value="Music")
tag2 = Tag.objects.create(value="Lyrics")
post = Post.objects.create(author=user, title="Yesterday", body="All my troubles seemed so far away")
post.tags.add(tag1)
post.tags.add(tag2)
expected_value = {
"author": user.username,
"id": user.id,
"title": post.title,
"body": post.body,
"tags": post.tags.all().values_list("value", flat=True),
}
response = post.serialize()
self.assertEqual(expected_value, response)
以及我正在测试的 Django 模型
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=False, null=False,)
title = models.CharField(blank=False, null=False, validators=[MinLengthValidator(3)], max_length=50)
body = models.CharField(blank=False, null=False, validators=[MinLengthValidator(5)], max_length=1000)
tags = models.ManyToManyField("Tag")
def serialize(self):
return {
"author": self.author.username,
"id": self.id,
"title": self.title,
"body": self.body,
"tags": self.tags.all().values_list("value", flat=True),
}
Can anybody explain me why these have the same values, but don't compare equal?
因为两个 QuerySet
objects [GitHub] 在 "carry" 相同的值时不被认为是相等的。只有对象本身相同,才会认为是相等的。实际上,如果您在 shell 中对此进行测试,您会检索到:
>>> MyModel.objects.all() == MyModel.objects.all()
False
>>> qs = MyModel.objects.all()
>>> qs == qs
True
毕竟一个QuerySet
不仅是一个值的集合,也是一个查询,检查两个查询是否等价,可能是一个undeciable problem [wiki].
因此您可以将其转换为带有 list(…)
的列表,例如:
expected_value = {
'author': user.username,
'id': user.id,
'title': post.title,
'body': post.body,
'tags': <b>list(</b>post.tags.values_list('value', flat=True)<b>)</b>,
}
以及在序列化程序中:
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(validators=[MinLengthValidator(3)], max_length=50)
body = models.CharField(validators=[MinLengthValidator(5)], max_length=1000)
tags = models.ManyToManyField("Tag")
def serialize(self):
return {
'author': self.author.username,
'id': self.id,
'title': self.title,
'body': self.body,
'tags': <b>list(</b>self.tags.values_list('value', flat=True)<b>)</b>
}
任何人都可以解释为什么它们具有相同的值,但不比较相等吗?很难理解这一点。使它们成为 "equal" 的最佳方法是什么?
使用 ipdb 检查:
ipdb> expected_value
{'author': 'john', 'id': 1, 'title': 'Yesterday', 'body': 'All my troubles seemed so far away', 'tags': <QuerySet ['Music', 'Lyrics']>}
ipdb> response
{'author': 'john', 'id': 1, 'title': 'Yesterday', 'body': 'All my troubles seemed so far away', 'tags': <QuerySet ['Music', 'Lyrics']>}
代码段:
class TestPost(TestCase):
def test_serialize(self):
user = User.objects.create(username="john", password="12345678", email="john@exemplo.com")
tag1 = Tag.objects.create(value="Music")
tag2 = Tag.objects.create(value="Lyrics")
post = Post.objects.create(author=user, title="Yesterday", body="All my troubles seemed so far away")
post.tags.add(tag1)
post.tags.add(tag2)
expected_value = {
"author": user.username,
"id": user.id,
"title": post.title,
"body": post.body,
"tags": post.tags.all().values_list("value", flat=True),
}
response = post.serialize()
self.assertEqual(expected_value, response)
以及我正在测试的 Django 模型
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=False, null=False,)
title = models.CharField(blank=False, null=False, validators=[MinLengthValidator(3)], max_length=50)
body = models.CharField(blank=False, null=False, validators=[MinLengthValidator(5)], max_length=1000)
tags = models.ManyToManyField("Tag")
def serialize(self):
return {
"author": self.author.username,
"id": self.id,
"title": self.title,
"body": self.body,
"tags": self.tags.all().values_list("value", flat=True),
}
Can anybody explain me why these have the same values, but don't compare equal?
因为两个 QuerySet
objects [GitHub] 在 "carry" 相同的值时不被认为是相等的。只有对象本身相同,才会认为是相等的。实际上,如果您在 shell 中对此进行测试,您会检索到:
>>> MyModel.objects.all() == MyModel.objects.all()
False
>>> qs = MyModel.objects.all()
>>> qs == qs
True
毕竟一个QuerySet
不仅是一个值的集合,也是一个查询,检查两个查询是否等价,可能是一个undeciable problem [wiki].
因此您可以将其转换为带有 list(…)
的列表,例如:
expected_value = {
'author': user.username,
'id': user.id,
'title': post.title,
'body': post.body,
'tags': <b>list(</b>post.tags.values_list('value', flat=True)<b>)</b>,
}
以及在序列化程序中:
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(validators=[MinLengthValidator(3)], max_length=50)
body = models.CharField(validators=[MinLengthValidator(5)], max_length=1000)
tags = models.ManyToManyField("Tag")
def serialize(self):
return {
'author': self.author.username,
'id': self.id,
'title': self.title,
'body': self.body,
'tags': <b>list(</b>self.tags.values_list('value', flat=True)<b>)</b>
}