我试图通过在JSONFields中存储某些对象来对我的Django Postgres数据库进行反规范化,该数据库支持JSON API:
https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/fields/#jsonfield
我扩展了django.contrib.postgres.fields.JSONField字段,以自动将数据序列化为Python对象。我这样做是为了将我的逻辑封装在对象周围并强制存储在JSONField中的对象的结构。我在这里关注自定义模型字段的Django文档:
https://docs.djangoproject.com/en/1.11/howto/custom-model-fields/
我能够将我的对象存储在自定义JSONField中,并且可以将它们检索为本机Python对象,但是,我已经破坏了管理控制台。当我尝试查看我的一个对象时,我收到此错误:
MYSQL *conn= mysql_init(NULL);
MYSQL_RES *res; /* holds the result set */
MYSQL_ROW row;
if(mysql_real_connect(conn, "xx.1x3.1xx.7x", "ixxx", "00000000", "xxx", 0, NULL, 0)){
char q[1000];
mysql_query(conn, "select id FROM user");
res = mysql_store_result(conn);
int num_fields = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)))
{
// Print all columns
for(int i = 0; i < num_fields; i++)
{
// Make sure row[i] is valid!
char *val = row[i];
std::cout << row[i][1] << std::endl;
//std::cout << "NULL" << std::endl;
// Also, you can use ternary operator here instead of if-else
// cout << row[i] ? row[i] : "NULL" << endl;
}
}
}
我认为问题在于内置的json.dumps函数不能很好地处理随机对象,所以我希望有一些方法可以在我的PostalAddress类中重写以使其发挥得很好。
这是我的代码,虽然这是一个简单的地址案例,我想将这个模式应用于更复杂和有用的自定义JSONField用例,所以我希望在管理控制台中看到序列化的JSON并且能够编辑文本并保存。
fields.py
TypeError: <core.fields.PostalAddress object at 0x7fdcfaade4e0> is not JSON serializable
models.py
from django.contrib.postgres.fields import JSONField
class PostalAddress(object):
def __init__(self, street='', city='', state='', postal_code=''):
self.street = street
self.city = city
self.state = state
self.postal_code = postal_code
def deserialize_address(address_dict):
return PostalAddress(**address_dict)
def get_empty_address():
return PostalAddress()
class PostalAddressField(JSONField):
description = "A postal address"
def __init__(self, *args, **kwargs):
super(PostalAddressField, self).__init__(*args, **kwargs)
def get_prep_value(self, value):
if value is None:
return value
if isinstance(value, PostalAddress):
return json.dumps(value.__dict__)
return value
def from_db_value(self, value, expression, connection, context):
if value is None:
return value
return deserialize_address(value)
def to_python(self, value):
if isinstance(value, PostalAddress):
return value
if value is None:
return value
return deserialize_address(value)
完整追踪:
from django.db import models
from .fields import PostalAddressField, get_empty_address
class Person(models.Model):
shipping_address = PostalAddressField(default = get_empty_address)
答案 0 :(得分:1)
你遇到的问题是Django使用它的JSONField
form field来尝试反序列化管理中的对象 - 这会失败,因为它只使用无法处理json.dumps()
对象的PostalAddress
。
您已覆盖模型字段,但您还需要覆盖管理员中使用的表单字段。该文档描述了如何specify a custom form field for a model field。
这样的事情:
from django.contrib.postgres.forms import JSONField
# Define a new form field
class PostalAddressJSONField(JSONField):
def prepare_value(self, value):
# Here, deserialize the object in a way that works.
# I've copied what you've done in your model field.
return json.dumps(value.__dict__)
然后在PostalAddressField
:
class PostalAddressField(JSONField):
def formfield(self, **kwargs):
defaults = {'form_class': PostalAddressJSONField}
defaults.update(kwargs)
return super().formfield(**defaults)
ModelAdmin
表单现在应该使用此自定义表单字段,并且能够正确反序列化。