web-dev-qa-db-ja.com

PeeweeモデルからJSONへ

私は、peeweeをORMとして使用してAPIを作成しています。peeweeモデルオブジェクトをJSONオブジェクトに変換してユーザーに送信する機能が必要です。これを行うための良い方法を誰かが知っていますか?

28
shoopdelang

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()は、関連するモデルを再帰し、後方参照モデルを含め、特定のフィールドをシリアル化から除外できることに注意してください。

75
coleifer

また、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)
3
kiba

私はこれと同じ問題を抱えており、自動的にシリアル化できないJSON型の独自のパーサー拡張を定義することになりました。今のところ、表現されるデータとして文字列を使用することに問題はありません(さまざまなデータ型を使用できる可能性がありますが、浮動小数点を使用した近似に注意してください!)

次の例では、これをutilsフォルダー内のjson_serialize.pyというファイルに入れます。

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を発生させてシリアル化できない型を見つけたらすぐに、新しい型をサポートするように更新します

0
Matteo Furlan

私は通常、最大限のセキュリティとコードの内部動作の理解のために、dict to dictとdict to model関数を実装します。 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']
        )
0
Ron Reiter