gpt4 book ai didi

Django 管理员 : object is not JSON serializable error on Custom Field Sub-classing JSONField

转载 作者:行者123 更新时间:2023-12-05 05:18:52 25 4
gpt4 key购买 nike

我正在尝试通过将某些对象存储在 JSONFields 中来对支持 JSON API 的 Django Postgres 数据库进行去规范化:

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 中,并可以将它们作为 native Python 对象检索,但是,我破坏了管理控制台。当我尝试查看我的一个对象时,出现此错误:

TypeError: <core.fields.PostalAddress object at 0x7fdcfaade4e0> is not JSON serializable

我认为问题是内置的 json.dumps 函数不能很好地处理随机对象,所以我希望我可以在我的 PostalAddress 类中重写一些方法来让它很好地播放。

这是我的代码,虽然这是一个简单的地址案例,但我想将此模式应用于更复杂和有用的自定义 JSONField 用例,所以我希望在管理控制台中看到序列化的 JSON 并且能够编辑文本并保存。

字段.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)

模型.py

from django.db import models
from .fields import PostalAddressField, get_empty_address

class Person(models.Model):
shipping_address = PostalAddressField(default = get_empty_address)

完整跟踪:

Request Method: GET
Request URL:...

Django Version: 1.11.6
Python Version: 3.5.2
Installed Applications:
['grappelli',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.postgres',
'rest_framework',
'rest_framework.authtoken',...
]
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']


Template error:
In template /home/ubuntu/venv/lib/python3.5/site-packages/grappelli/templates/admin/includes/fieldset.html, error at line 24
<core.fields.PostalAddress object at 0x7f2c7fc085f8> is not JSON serializable 14 : {% if field.is_checkbox %}
15 : <div class="c-1">&nbsp;</div>
16 : <div class="c-2">
17 : {{ field.field }}{{ field.label_tag|prettylabel }}
18 : {% else %}
19 : <div class="c-1">{{ field.label_tag|prettylabel }}</div>
20 : <div class="c-2">
21 : {% if field.is_readonly %}
22 : <div class="grp-readonly">{{ field.contents }}</div>
23 : {% else %}
24 : {{ field.field }}
25 : {% endif %}
26 : {% endif %}
27 : {% if line.fields|length_is:'1' %}{{ line.errors }}{% endif %}
28 : {% if not line.fields|length_is:'1' and not field.is_readonly %}{{ field.field.errors }}{% endif %}
29 : {% if field.field.help_text %}
30 : <p class="grp-help">{{ field.field.help_text|safe }}</p>
31 : {% endif %}
32 : </div>
33 : </div>
34 : {% endfor %}


Traceback:

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
217. response = self.process_exception_by_middleware(e, request)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
215. response = response.render()

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/response.py" in render
107. self.content = self.rendered_content

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/response.py" in rendered_content
84. content = template.render(context, self._request)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/backends/django.py" in render
66. return self.template.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
207. return self._render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
177. return compiled_parent._render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
177. return compiled_parent._render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
72. result = block.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
72. result = block.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
216. nodelist.append(node.render_annotated(context))

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/loader_tags.py" in render
216. return template.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
209. return self._render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in _render
199. return self.nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
411. return strip_spaces_between_tags(self.nodelist.render(context).strip())

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
216. nodelist.append(node.render_annotated(context))

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
216. nodelist.append(node.render_annotated(context))

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
322. return nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/defaulttags.py" in render
322. return nodelist.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
990. bit = node.render_annotated(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_annotated
957. return self.render(context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render
1046. return render_value_in_context(output, context)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/template/base.py" in render_value_in_context
1024. value = force_text(value)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/utils/encoding.py" in force_text
76. s = six.text_type(s)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/utils/html.py" in <lambda>
385. klass.__str__ = lambda self: mark_safe(klass_str(self))

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/forms/boundfield.py" in __str__
40. return self.as_widget() + self.as_hidden(only_initial=True)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/forms/boundfield.py" in as_widget
125. value=self.value(),

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/forms/boundfield.py" in value
162. return self.field.prepare_value(data)

File "/home/ubuntu/venv/lib/python3.5/site-packages/django/contrib/postgres/forms/jsonb.py" in prepare_value
55. return json.dumps(value)

File "/usr/lib/python3.5/json/__init__.py" in dumps
230. return _default_encoder.encode(obj)

File "/usr/lib/python3.5/json/encoder.py" in encode
198. chunks = self.iterencode(o, _one_shot=True)

File "/usr/lib/python3.5/json/encoder.py" in iterencode
256. return _iterencode(o, 0)

File "/usr/lib/python3.5/json/encoder.py" in default
179. raise TypeError(repr(o) + " is not JSON serializable")

Exception Type: TypeError at /admin/...
Exception Value: <core.fields.PostalAddress object at 0x7f2c7fc085f8> is not JSON serializable

最佳答案

您遇到的问题是 Django 使用它的 JSONField form field尝试反序列化管理员中的对象 - 这失败了,因为它仅使用 json.dumps() 无法处理您的 PostalAddress 对象。

您已经覆盖了 model 字段,但您还需要覆盖管理中使用的 form 字段。该文档描述了如何 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 表单现在应该使用这个自定义表单字段,并且能够正确反序列化它。

关于Django 管理员 : object is not JSON serializable error on Custom Field Sub-classing JSONField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47116153/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com