Django测试模板中如何将字符串转为带等号的Model过滤条件?
解决Django测试模板中复用Model查询条件的问题
我明白你想打造一个可复用的测试模板,减少重复代码,但卡在了如何用统一配置的查询条件来复用Model查询这一步。咱们来一步步搞定这个问题:
问题根源
你之前用eval(model_criteria)的思路走不通,是因为model_criteria是字符串格式的'first_name="First"',eval之后得到的是一个表达式结果(比如布尔值),而Django的filter()/get()方法需要的是关键字参数(kwargs),不是表达式。直接用eval不仅达不到目的,还存在安全风险,绝对不推荐。
最优解决方案:用字典存储查询条件
最符合Python和Django习惯的方式,就是把查询条件直接定义成字典,然后用Python的字典解包语法传给QuerySet方法。这样既安全又易读,还能完美复用。
修改你的代码如下:
# 视图路径 # '/app/view/path/' view_name = 'service:create_employee_profile' # 用于测试表单提交成功的有效字段值 valid_values = { 'first_name': 'First', 'last_name': 'Last', } # Model的get和filter查询条件:直接用字典存储键值对 model_criteria = {'first_name': 'First'} """ 测试:提交表单 """ # 测试:视图保存有效对象 def test_view_saves_valid_object(self): response = self.client.post( reverse(view_name), valid_values) # 用**解包字典,转换成filter需要的first_name="First"格式 self.assertTrue(Model.objects.filter(**model_criteria).exists())
复用扩展
这个字典可以在所有需要查询该对象的测试用例里复用,比如:
def test_saved_object_has_correct_last_name(self): self.client.post(reverse(view_name), valid_values) # 同样用**解包字典查询对象 saved_obj = Model.objects.get(**model_criteria) self.assertEqual(saved_obj.last_name, valid_values['last_name'])
特殊场景:从字符串解析查询条件
如果因为某些特殊需求(比如从外部配置读取)必须用字符串格式的条件,也不要用eval,而是用安全的解析方式转换成字典。比如:
方式1:用字典格式的字符串 + ast.literal_eval
import ast # 定义成字典格式的字符串 model_criteria_str = "{'first_name': 'First', 'last_name': 'Last'}" # 用ast.literal_eval安全解析成字典(比eval安全100倍) model_criteria = ast.literal_eval(model_criteria_str) # 之后同样用**解包使用 Model.objects.filter(**model_criteria)
方式2:自定义解析简单的键值对字符串
如果你的字符串是"first_name=First,last_name=Last"这种格式,可以写个简单的解析函数:
def parse_criteria(criteria_str): criteria = {} for pair in criteria_str.split(','): # 只拆分第一个等号,避免值里包含等号的情况 key, value = pair.strip().split('=', 1) # 处理带引号的值 if value.startswith(('"', "'")) and value.endswith(('"', "'")): value = value[1:-1] criteria[key] = value return criteria # 使用示例 model_criteria_str = 'first_name="First"' model_criteria = parse_criteria(model_criteria_str) Model.objects.filter(**model_criteria)
这样处理后,你就能在测试模板顶部统一管理所有配置变量,轻松复用在多个测试用例里啦!
内容的提问来源于stack exchange,提问作者Carl Brubaker
相关产品推荐
相关产品推荐

