Django中如何通过__str__方法返回值获取对应模型对象
解答
强烈不推荐通过__str__()返回值反向查询Clause实例,核心原因有三个:
__str__()的定位是面向人类的可读展示文本,不是稳定的查询标识,后续只要调整__str__的拼接规则,所有反查逻辑会直接失效- 拼接字符串没有唯一约束,一旦出现两个条款的
reference_number和title组合重复,反查会触发多结果报错 - 字符串拆分匹配性能差,还容易因为字段内容本身包含分隔符
:出现匹配错误
最优解决思路:从表单渲染层规避反查需求
你提交后拿到字符串,本质是下拉选项的value配置错了。Django设计模型下拉选择的标准逻辑是:选项展示文本用__str__()返回值,选项实际提交值用模型主键,后端拿到主键直接就能查到对应实例,完全不需要反查。
如果是手动渲染下拉框,按如下写法配置option的value即可:
<select name="clause"> {% for clause in clauses %} <option value="{{ clause.pk }}">{{ clause }}</option> {% endfor %} </select>
后端直接用接收到的主键查询:
selected_clause = Clause.objects.get(pk=request.POST["clause"])
如果是用Django内置表单类,直接使用ModelChoiceField,框架会自动完成主键和实例的映射,校验通过后从cleaned_data中取到的直接就是Clause实例:
from django import forms class MyForm(forms.Form): clause = forms.ModelChoiceField(queryset=Clause.objects.all())
兜底反查方案(仅用于无法修改表单提交值的场景)
如果你确实只能拿到__str__()返回的拼接字符串,可以按__str__的拼接规则拆分后匹配字段,注意拆分时限制最多拆分1次,避免title本身包含: 导致拆分错误:
recv_str = request.POST.get("clause") reference_number, title = recv_str.split(": ", maxsplit=1) try: selected_clause = Clause.objects.get( reference_number=reference_number, title=title ) except Clause.DoesNotExist: selected_clause = None except Clause.MultipleObjectsReturned: # 出现重复数据时取第一条,可根据业务需求调整处理逻辑 selected_clause = Clause.objects.filter( reference_number=reference_number, title=title ).first()
该方案仅为临时兜底方案,只要条件允许请优先使用主键传值的标准实现。
内容的提问来源于stack exchange,提问作者Panda
相关产品推荐
相关产品推荐

