本人是 python 初级程序员, 今天在公司测试服务器遇到一个数据库存储的问题, 原本存储在数据库中的字段值 '{"first": ["", ""], "second": ["", ""]}' 变成了 '{{first, "", ""}, {second, "", ""}}',first 没有引号!!!, 而且突然有了 {{ 和 }} 是什么意思? 这里主要设计 django 的两个 model, 定义如下:
class A(models.Model):
params = JSONField(verbose_name="A",default=dict)
class B(models.Model):
template = models.ForeignKey(A, verbose_name='B')
存储 A 中一条记录的语句:
d = dict()
d["first"] = ["", ""]
d["second"] = ["", ""]
A.objects.create(params=d)
我在使用 A 的增删改查操作时 数据库记录都是正确的, 但是服务器第二天就报错了, 初步排查, 代码中只有一处对 A 表进行操作, 应该不是存储格式错误的原因,在服务器中使用 psql 查询 A 表时发现存储的数据 由原来的 {"first": ["", ""], "second": ["", ""]} 变成 {{first, "", ""}, {second, "", ""}},这是 postgresql 数据库的一个 bug 吗? 因为 9.3 版本不支持 jsonb, 所以自定义了一个 JSONField , 定义如下:
class JSONField(Field):
empty_strings_allowed = True
default_error_messages = {
'invalid': "Value must be valid JSON.",
}
description = 'A JSON object'
_encoder_class = {
"indent": None,
"sort_keys": True,
"separators": (',', ':'),
"skipkeys": True,
}
_decoder_kwargs = {
"object_hook": hook_handler
}
def __init__(self, *args, **kwargs):
if not kwargs.get('null', False):
kwargs['default'] = kwargs.get('default', dict)
self.encoder_kwargs = dict(
kwargs.pop(
'encoder_kwargs', self._encoder_class))
self.decoder_kwargs = dict(
kwargs.pop(
'decoder_kwargs', self._decoder_kwargs))
super(JSONField, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
defaults = {
'form_class': JSONFormField,
'widget': JSONWidget,
}
defaults.update(**kwargs)
return super(JSONField, self).formfield(**defaults)
def validate(self, value, model_instance):
super(JSONField, self).validate(value, model_instance)
try:
json.dumps(value)
except TypeError:
raise ValidationError(
self.error_messages['invalid'],
code='invalid',
params={'value': value},
)
def get_internal_type(self):
return 'TextField'
def db_type(self, connection):
# if connection.vendor == 'postgresql' and connection.pg_version >= 90400:
# raise ValueError("使用 django.contrib.postgres.fields.JSONField")
return 'text'
def from_db_value(self, value, expression, connection, context):
if value is None:
return None
return json.loads(value, **self.decoder_kwargs)
def get_prep_value(self, value):
if value is None:
if self.null and self.blank:
return None
value = ""
return json.dumps(value, **self.encoder_kwargs)
def value_to_string(self, obj):
return self.value_from_object(obj)
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.