我正在使用 peewee 作为 ORM 创建一个 API,我需要能够将 peewee 模型对象转换为 JSON 对象以发送给用户。有谁知道这样做的好方法?
7 回答
Peewee在扩展模块中有一个model_to_dict
和dict_to_model
助手。playhouse.shortcuts
- http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#model_to_dict
- http://docs.peewee-orm.com/en/latest/peewee/playhouse.html#dict_to_model
您可以按如下方式使用它们:
from playhouse.shortcuts import model_to_dict, dict_to_model
user_obj = User.select().where(User.username == 'charlie').get()
json_data = json.dumps(model_to_dict(user_obj))
另请注意,model_to_dict()
可以通过相关模型进行递归,包括反向引用模型,并排除某些字段被序列化。
单取时
user = User.select().where(User.id == 1).get()
model_to_dict(user) #to Dict
多取时
users = list(User.select().where(User.name ** 'a%').dicts())
此外,您可以将模型作为 dict,然后转换为具有正确字段类型(bool、int、float 等)的 json:
import peewee
import json
from bson import json_util
from datetime import datetime
class User(peewee.Model):
email = CharField()
status = BooleanField(default=True)
firstname = CharField()
lastname = CharField()
age = IntegerField()
created = DateTimeField(default=datetime.now())
class Meta:
database = db
user = User.select().dicts().get()
print json.dumps(user, default=json_util.default)
对于任何有类似问题的人TypeError: Object of type date is not JSON serializable
,这对我有用(在 Python 3.8.2 上测试)。
from playhouse.shortcuts import model_to_dict
import json
def print_model(model):
print(json.dumps(model_to_dict(model), indent=4, sort_keys=True, default=str))
def print_models(models):
print(json.dumps(list(models.dicts()), indent=4, sort_keys=True, default=str))
用法 1 - 单一模型
for person in Person.select():
print_model(person)
用法 2 - 许多型号
print_models(Person.select())
我通常实现模型来 dict 和 dict 来建模函数,以获得最大的安全性和对代码内部工作原理的理解。Peewee 做了很多魔法,你想控制它。
为什么不应该迭代字段而是明确指定它们的最明显的论点是出于安全考虑。并非所有字段都可以向用户公开,我假设您需要此功能来实现某种 REST API。
所以 - 你应该做这样的事情:
class UserData(db.Model):
user = db.ForeignKeyField(User)
data = db.CharField()
def serialize():
# front end does not need user ID here
return {
'data': self.data
}
@classmethod
def from_json(cls, json_data):
UserData.create(
# we enforce user to be the current user
user=current_user,
data=json_data['data']
)
我遇到了同样的问题,最终为无法自动序列化的 JSON 类型定义了自己的解析器扩展。我现在可以使用字符串作为数据表示(尽管您可能会使用不同的数据类型,但要注意使用浮点数进行近似!
在以下示例中,我将其放入文件夹json_serialize.py
内的一个文件中utils
:
from decimal import Decimal
import datetime
try:
import uuid
_use_uuid = True
except ImportError:
_use_uuid = False
datetime_format = "%Y/%m/%d %H:%M:%S"
date_format = "%Y/%m/%d"
time_format = "%H:%M:%S"
def set_datetime_format(fmt_string):
datetime_format = fmt_string
def set_date_format(fmt_string):
date_format = fmt_string
def set_time_format(fmt_string):
time_format = fmt_string
def more(obj):
if isinstance(obj, Decimal):
return str(obj)
if isinstance(obj, datetime.datetime):
return obj.strftime(datetime_format)
if isinstance(obj, datetime.date):
return obj.strftime(date_format)
if isinstance(obj, datetime.time):
return obj.strftime(time_format)
if _use_uuid and isinstance(obj, uuid.UUID):
return str(obj.db_value())
raise TypeError("%r is not JSON serializable" % obj)
然后,在我的应用程序中:
import json
from utils import json_serialize
...
json.dumps(model_to_dict(User.get()), default=json_serialize.more)
编辑只是添加:这在很大程度上受到了json_utils.default
mongodb 中的模块的启发,但主要依赖于json
模块,不需要导入 mongodb 自己的 bson/json_utils 模块。
通常我会在我的应用程序提出后立即更新它以支持新类型,因为TypeError
它发现了一种无法序列化的类型
你可以这样做:
class MyModel(peewee.Model):
def __str__(self):
r = {}
for k in self._data.keys():
try:
r[k] = str(getattr(self, k))
except:
r[k] = json.dumps(getattr(self, k))
return str(r)
class User(MyModel):
email = CharField()
status = CharField(default="enabled")
firstname = CharField()
lastname = CharField()
class Meta:
database = db