我有一个非常简单的模型,其中包含一个JSONField
class Thing(models.Model):
title = models.CharField(max_length=1024)
text = JSONField(default=dict)我已经创建了一个自定义小部件,它允许输入键值对:
class JsonWidget(forms.widgets.Widget):
template_name = 'json_widget.html'
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
data = json.loads(value)
if not data:
data = JSON_DEFAULT
context['data'] = data.items()
return context
def value_from_datadict(self, data, files, name):
keys = data.getlist('json-key')
values = data.getlist('json-value')
json_data = {k: v for k, v in zip(keys, values)}
return json_data我将小部件返回的dict强制转换为表单上字段的clean函数中的字符串:
class ThingForm(forms.ModelForm):
class Meta:
model = Thing
fields = ['title', 'text']
widgets = {
'text': JsonWidget(),
}
def clean_text(self):
text = self.cleaned_data.get('text')
return json.dumps(text)我已经检查过JsonWidget.value_from_datadict (dict)和ThingForm.clean_text (str)的输出是预期的类型。但是当对象去保存时,它会抛出一个异常:
TypeError: the JSON object must be str, bytes or bytearray, not 'dict'这是我第一次为Django 1.11构建自定义小部件,这里有什么明显的遗漏吗?
谢谢!
发布于 2019-02-13 11:42:51
这是一个棘手的问题,但我最终将问题追溯到了Instance construction fails on form data check
虽然JSONField在模型上称为text,但在ModelForm上没有匹配的字段。相反,键/值对被小部件的value_from_datadict编译并转换为dict。但是,只有当表单的POST数据中存在字段名称时,cleaned_data值才会保存回实例。这导致小部件抛出错误,因为text不能为空,并且在表单重新呈现期间引发了TypeError异常。
解决方法是向字段添加一个名为text的隐藏输入,并仅使用它在实例化过程中绕过字段名检查。
https://stackoverflow.com/questions/54644857
复制相似问题