Django==2.2.2:能否执行构造的字段赋值语句?求优雅优化方案
关于Django动态更新模型字段的优化方案
嘿,你提到的用字符串拼接后执行代码的写法其实能运行,但非常不推荐!
首先,你写的execute(tmp)应该是Python的exec(tmp)吧?这种方式的问题很大:
- 安全性极差:如果
what_to_update变量被恶意篡改(比如传入类似"__import__('os').system('rm -rf /')"的字符串),exec会直接执行这段危险代码,给系统带来毁灭性风险。 - 可读性与维护性差:这种“字符串拼接代码”的写法完全不符合常规编码规范,后续接手的开发者很难快速理解逻辑,排查问题也会非常麻烦。
推荐的优雅优化方案:用setattr()动态设置属性
Python内置的setattr()函数就是专门用来动态设置对象属性的,完全适配你的场景,安全又简洁。结合字段合法性校验,代码可以改成这样:
import json from django.core.exceptions import FieldDoesNotExist yandex_response_record, created = YandexResponse.objects.get_or_create(id=1) try: # 先校验字段是否存在于YandexResponse模型中 YandexResponse._meta.get_field(what_to_update) # 动态设置对应字段的值 setattr(yandex_response_record, what_to_update, json.dumps(data)) yandex_response_record.save() except FieldDoesNotExist: # 处理非法字段的情况,比如抛出异常或记录日志 raise ValueError(f"无法更新不存在的字段:{what_to_update}")
为什么这个方案更好?
- 安全可控:通过Django模型的
_meta.get_field()校验字段合法性,避免了恶意输入或错误字段的风险。 - 代码简洁:一行
setattr替代了冗长的多分支判断,逻辑清晰,代码量大大减少。 - 扩展性强:如果后续YandexResponse模型新增字段,不需要修改这段代码,自动支持新字段的更新。
如果你觉得用_meta.get_field()有点繁琐,也可以手动维护一个允许更新的字段集合,写法更轻量:
yandex_response_record, created = YandexResponse.objects.get_or_create(id=1) allowed_fields = {"campaigns", "ad_groups", "ads", "keywords", "sitelinks"} if what_to_update in allowed_fields: setattr(yandex_response_record, what_to_update, json.dumps(data)) yandex_response_record.save() else: raise ValueError(f"无法更新不存在的字段:{what_to_update}")
这两种方式都比用exec靠谱得多,完全符合Python和Django的最佳实践。
内容的提问来源于stack exchange,提问作者Trts
相关产品推荐
相关产品推荐

