Python中PostgreSQL 9.3.5数据库存储字典型数据遇到的一个问题

本人是 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)


Python中PostgreSQL 9.3.5数据库存储字典型数据遇到的一个问题

2 回复

我无法理解你的问题


看起来像是函数 get_prep_value 的问题,不知道你的 JSONField 怎么写出来的。
我的话,会在 Django 自带的 JSONField 上调整,楼主可以试试。

<br>from django.contrib.postgres.fields.jsonb import JSONField as JSONBField<br><br>class JSONField(JSONBField):<br> def db_type(self, connection):<br> return 'json'<br>

回到顶部