我正在使用peewee作为ORM创建API,我需要能够将peewee模型对象转换为JSON对象以发送给用户。有谁知道这样做的好方法?
答案 0 :(得分:69)
Peewee在model_to_dict
扩展模块中有dict_to_model
和playhouse.shortcuts
个助手。
您可以按如下方式使用这些:
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()
可以通过相关模型递归,包括反向引用的模型,并排除某些字段被序列化。
答案 1 :(得分:3)
另外,你可以将模型作为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)
答案 2 :(得分:1)
对于遇到诸如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())
答案 3 :(得分:0)
我通常将模型实现为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']
)
答案 4 :(得分:0)
我遇到了同样的问题,最终为无法自动序列化的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)
仅需添加以下内容:这很大程度上是受mongodb中的json_utils.default
模块启发,但主要依赖于json
模块,不需要导入mongodb自己的bson / json_utils模块。
通常,我会在应用程序引发TypeError
时发现它无法序列化,因此我会对其进行更新以支持新类型
答案 5 :(得分:0)
user = User.select().where(User.id == 1).get()
model_to_dict(user) #to Dict
users = list(User.select().where(User.name ** 'a%').dicts())
答案 6 :(得分:-2)
你可以这样做:
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