Django调用Workout.objects.all()出现TypeError的原因排查
解决Django自定义字段
from_db_value()参数不匹配的错误 你遇到的这个报错根源很明确——自定义字段的from_db_value()方法参数签名和当前Django版本不兼容。
问题分析
Django在版本迭代中给from_db_value()方法新增了第5个参数context,而你定义的LiftsField和CardiosField里的这个方法只声明了4个参数(value, expression, connection),当Django尝试传入完整的5个参数时,就触发了参数不匹配的类型错误。
另外还要提个隐藏问题:你的parse_cardios函数没有返回值,这会导致CardiosField在解析数据库值时返回None,后续必然会引发新的逻辑错误,这个也要一起修复。
修复步骤
- 给两个自定义字段的
from_db_value()方法添加context参数(可以设置默认值None,避免影响现有逻辑) - 补全
parse_cardios函数的返回语句
修改后的fields.py代码如下:
import json # 请确保导入了对应的models模块,比如from . import models def parse_lifts(lifts_string): """Takes a string of json and turns it into a Lifts object""" series = json.loads(lifts_string) serie_objects = [models.LiftSerie(serie["liftname"], serie["setlist"]) for serie in series] return models.Lifts(serie_objects) def parse_cardios(cardios_string): """Takes a string of json and turns it into a Cardios Object""" series = json.loads(cardios_string) serie_objects = [models.CardioSerie(serie["cardioname"], serie["duration"]) for serie in series] # 补全返回语句,返回构建好的Cardios对象 return models.Cardios(serie_objects) class LiftsField(JSONField): """Field representing a models.Lifts object""" # 添加context参数并设置默认值None def from_db_value(self, value, expression, connection, context=None): if value is None: return value return parse_lifts(value) def to_python(self, value): if isinstance(value, models.Lifts): return value if value is None: return value return parse_lifts(value) def get_prep_value(self, value): if not value: return value lifts_pre_json = [serie_object.pre_json() for serie_object in value.series] return json.dumps(lifts_pre_json) class CardiosField(JSONField): """Field representing a models.Cardios object""" # 添加context参数并设置默认值None def from_db_value(self, value, expression, connection, context=None): if value is None: return value return parse_cardios(value) def to_python(self, value): if isinstance(value, models.Cardios): return value if value is None: return value return parse_cardios(value) def get_prep_value(self, value): if value == None: return value cardios_pre_json = [serie_object.pre_json() for serie_object in value.series] return json.dumps(cardios_pre_json)
验证修复
修改代码后重启Django Shell,再次执行Workout.objects.all(),应该就能正常返回查询集了。
内容的提问来源于stack exchange,提问作者Sahand
相关产品推荐
相关产品推荐

