
本人是 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) 1 siteshen 2017 年 12 月 19 日 看起来像是函数 `get_prep_value` 的问题,不知道你的 JSONField 怎么写出来的。 我的话,会在 Django 自带的 JSONField 上调整,楼主可以试试。 ``` from django.contrib.postgres.fields.jsonb import JSONField as JSONBField class JSONField(JSONBField): def db_type(self, connection): return 'json' ``` |