現在、ほとんどのWebフレームワークと同様に、シリアライゼーションの作業には、モデルをある種の形式にダンプするメソッド呼び出しがあります。私たちの場合、フィールド名と値をインスタンス変数とするキー値辞書を作成して返すすべてのモデルに対して、to_dict()
メソッドがあります。アクセス制御を尊重しながらREST APIのSQLAlchemyモデルをシリアライズしますか?
コード全体に次のようなスニペットがあります。json.dumps(**some_model_object.to_dict())
some_model_object
をjsonにシリアル化します。最近、我々はいくつかの内部リソースをユーザーに公開することに決めましたが、これらのリソースの中には、要求ユーザーがスーパーユーザーでない場合にシリアル化中に返信したくない特定のプライベートインスタンス値があります。
私はjson以外の形式にシリアル化できるようにするだけでなく、シリアライズを容易にするクリーンなデザインを考え出しています。私はこれがAspect Oriented Design/Programmingのかなり良いユースケースだと思っています.Aspect Oriented Design/Programmingでは、アスペクトがリクエストしているアクセスコントロールを尊重し、リクエストするユーザの欲求に基づいてオブジェクトをシリアライズします。今、私はカップルに現在のリクエストでデータベースのモデルを持っているので、
from framework import current_request
class User(SQLAlchemyDeclarativeModel):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
first_name = Column(Unicode(255))
last_name = Column(Unicode(255))
private_token = Column(Unicode(4096))
def to_dict(self):
serialized = dict((column_name, getattr(self, column_name))
for column_name in self.__table__.c.keys())
# current request might not be bound yet, could be in a unit test etc.
if current_request and not current_request.user.is_superuser():
# we explicitly define the allowed items because if we accidentally add
# a private variable to the User table, then it might be exposed.
allowed = ['id', 'first_name', 'last_name']
serialized = dict((k, v) for k, v in serialized.iteritems() if k in allowed)
return serialized
1が見ることができるように、これは理想的な未満です:
は、ここで私が今持っているものに似たものです。これは非常に明白ですが、リクエストカップリングはコードの匂いです。私はこれをきれいに行う方法を見出そうとしています。私はそれがそうのようなモデルにいくつかのフィールドを登録することであることについて考えた
一つの方法:
class User(SQLAlchemyDeclarativeModel):
__tablename__ = 'users'
__public__ = ['id', 'first_name', 'last_name']
__internal__ = User.__exposed__ + ['private_token']
id = Column(Integer, primary_key=True)
first_name = Column(Unicode(255))
last_name = Column(Unicode(255))
private_token = Column(Unicode(4096))
その後、私はすべてのWSGIコールに現在のリクエストにバインドされたシリアライザクラスを持っているでしょう必要なシリアライザを使用します。たとえば、次のように
import simplejson
from framework import JSONSerializer # json serialization strategy
from framework import serializer
# assume response format was requested as json
serializer.register_serializer(JSONSerializer(simplejson.dumps))
serializer.bind(current_request)
はその後、私のビューのどこかに、私はどうなる:次のように
from framework import Response
user = session.query(User).first()
return Response(code=200, serializer.serialize(user))
serialize
が実施される。このアプローチの読みやすさと明快に
def serialize(self, db_model_obj):
attributes = '__public__'
if self.current_request.user.is_superuser():
attributes = '__private__'
payload = dict((c, getattr(db_model_obj, c))
for c in getattr(db_model_obj, attributes))
return self.serialization_strategy.execute(payload)
思考?これは問題のpythonicアプローチですか?
ありがとうございます。
変数Cの名前はわかりません。 :)そして私はserialization_strategyのようなものについて私の予約を持っています。クラスはすでにシリアライザであるため、冗長であり、デザインパターンの名前が落ちているようです。これは、関連するクラスを訪れる戦略のように、より具体的なものであると私は想定していますか?私はあなたが実際にあなたのフレームワーク「フレームワーク」に名前をつけるつもりはないことを願っています。 :) –