我在JSONField上阅读the docs,这是一种特殊的postgresql字段类型。因为我打算创建一个子类JSONField
的自定义字段,并添加了能够转换Lifts
类的功能:
class Lifts(object):
def __init__(self, series):
for serie in series:
if type(serie) != LiftSerie:
raise TypeError("List passed to constructor should only contain LiftSerie objects")
self.series = series
class AbstractSerie(object):
def __init__(self, activity, amount):
self.activity_name = activity.name
self.amount = amount
def pre_json(self):
"""A dict that can easily be turned into json."""
pre_json = {
self.activity_name:
self.amount
}
return pre_json
def __str__(self):
return str(self.pre_json())
class LiftSerie(AbstractSerie):
def __init__(self, lift, setlist):
""" lift should be an instance of LiftActivity.
setList is a list containing reps for each set
that has been performed.
"""
if not (isinstance(setlist, collections.Sequence) and not isinstance(setlist, str)):
raise TypeError("setlist has to behave as a list and can not be a string.")
super().__init__(lift, setlist)
我已阅读here to_python()
和from_db_value()
是Field
类中的两个方法,这些方法涉及从数据库加载值并对其进行反序列化。此外,在Field
class上的to_python()
方法的docstring中,它表示它应该被子类覆盖。所以,我查看JSONField
。猜猜是什么,它不会覆盖它。此外,from_db_value()
甚至未在Field
上定义(也不在JOSNField
上)。
那么这里发生了什么?这使得很难理解JSONField如何获取值并将它们转换为json并将它们存储在数据库中,然后在我们查询数据库时则相反。
我的问题摘要:
to_python()
未覆盖JSONField
?from_db_value()
未覆盖JSONField
?from_db_value()
上没有定义Field
?JSONField
如何以python dict
为例,将其转换为JSON字符串,并将其存储在数据库中?很抱歉很多问题,但我真的很想理解这一点,而且文档有点缺乏IMO。
答案 0 :(得分:2)
对于Django数据库字段,有三个相同状态/表示相同的数据:form,python和database。在示例HandField
的情况下,表单/数据库表示是相同的字符串,python表示是Hand
对象实例。
如果自定义字段位于JSONField
之上,则内部python可能是LiftSerie
实例,表单表示为json字符串,值为json字符串发送给数据库的值和值从数据库中收到一个由psycopg2转换的json结构,如果有意义的话,将从postgres返回的字符串中获取。
就你的问题而言:
python值未自定义,因此该字段的python数据类型与预期输入相同。与HandField
示例相反,输入可以通过字符串或Hand
实例进行。在后一种情况下,只返回输入的基础Field.to_python()
实现就足够了。
Psycopg2已将数据库值转换为json,请参阅5.对于其他类型(如int / IntegerField
)也是如此。
from_db_value
未在基础Field
类中定义,但如果存在,则肯定会将其考虑在内。如果您查看implementation of Field.get_db_converters()
,如果from_db_value
具有名称相同的属性,则会Field
添加django.contrib.postgres.JSONField
。
<script src="assets/extraQU/extraQU.js"></script>
有一个可选的编码器参数。默认情况下,它使用json.dumps
without an encoder将json结构转换为JSON字符串。
psycopg2自动从数据库类型转换为python类型。它被称为adaptation。 Documentation for JSON adaptation解释了它是如何工作的,并且可以自定义。
请注意,在实现自定义字段时,我建议在开发期间为其编写测试,尤其是在机制未完全理解的情况下。您可以获得此类测试的灵感,例如django-localflavor。
答案 1 :(得分:0)
简单的答案是,to_python和from_db_value都返回python字符串,这些字符串应序列化为JSON,且所有条件均相同。
如果您对字符串没问题,那很好,但是我通常重写Django JSONFields的from_db_value方法以返回字典或列表,而不是在我的代码中使用的字符串。我为此创建了一个自定义字段。
对我来说,Json字段的全部要点是能够与其作为字典或列表的值进行交互。