关于Django 2 TestCase assertQuerysetEqual的疑问:验证模型Meta排序
测试Django模型Meta类排序的正确姿势
看起来你是想验证Django模型Meta类里的排序配置是否生效,还纠结于assertQuerysetEqual的用法对吧?我来帮你把这个测试用例理清楚,顺便纠正下可能对这个断言方法的误解~
先补全你的模型代码
首先我先把你没写完的Meta类补全(假设你要按姓氏、名字升序排序,你可以根据实际需求调整排序字段):
# models.py class Name(models.Model): first_name = models.CharField( "First Name", max_length=100, ) middle_name = models.CharField( "Middle Name or Initial", max_length=100, default='', ) last_name = models.CharField( "Last Name", max_length=200, ) class Meta: # 按姓氏升序,再按名字升序排序 ordering = ['last_name', 'first_name']
编写测试用例的正确方式
这里要重点注意:assertQuerysetEqual默认会对比查询集中每个对象的repr()结果,这很容易因为模型__repr__的细节(比如默认字段值)导致测试失败,所以更可靠的做法是指定transform参数,或者直接提取字段值来对比。
方式一:使用transform参数对比实例标识
# tests.py from django.test import TestCase from .models import Name class NameModelSortingTestCase(TestCase): def setUp(self): # 故意打乱顺序创建测试数据,方便验证排序效果 self.smith_john = Name.objects.create(first_name="John", last_name="Smith") self.adams_alice = Name.objects.create(first_name="Alice", last_name="Adams") self.smith_emily = Name.objects.create(first_name="Emily", last_name="Smith") def test_meta_ordering_works(self): # 获取所有Name对象,会自动应用Meta里的排序规则 queryset = Name.objects.all() # 预期的排序顺序:Adams Alice → Smith Emily → Smith John expected_objects = [self.adams_alice, self.smith_emily, self.smith_john] # 用transform指定对比对象的pk,确保是同一个实例 self.assertQuerysetEqual( queryset, expected_objects, transform=lambda obj: obj.pk )
方式二:直接对比字段值组合
如果你更关注排序后的字段顺序,也可以把查询集转成字段元组的列表,直接和预期列表对比:
def test_meta_ordering_by_fields(self): queryset = Name.objects.all() # 预期的字段顺序 expected_order = [ ("Alice", "Adams"), ("Emily", "Smith"), ("John", "Smith") ] # 从查询集中提取字段组合 actual_order = [(obj.first_name, obj.last_name) for obj in queryset] self.assertEqual(actual_order, expected_order)
额外验证技巧:查看生成的SQL
如果你想确认Django是否生成了正确的排序SQL,可以打印查询集的query属性:
print(Name.objects.all().query) # 输出会包含:ORDER BY "your_app_name"."last_name" ASC, "your_app_name"."first_name" ASC
这样就能彻底确认你的Meta排序配置是符合预期的啦~
内容的提问来源于stack exchange,提问作者Carl Brubaker
相关产品推荐
相关产品推荐

