1

ここでPython初心者、

現在、私はSQLAlchemyを使用していますが、これがあります:

from __init__ import Base
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer, String
from sqlalchemy.orm import relationship

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True)
    username = Column(String, unique=True)
    email = Column(String)
    password = Column(String)
    salt = Column(String)
    openids = relationship("OpenID", backref="users")

User.__table__.create(checkfirst=True)

#snip definition of OpenID class

def create(**kwargs):
    user = User()
    if "username" in kwargs.keys():
        user.username = kwargs['username']
    if "email" in kwargs.keys():
        user.username = kwargs['email']
    if "password" in kwargs.keys():
        user.password = kwargs['password']

    return user

これは に/db/users.pyあるので、次のように使用されます。

from db import users
new_user = users.create(username="Carson", password="1234")
new_user.email = "email@address.com"
users.add(new_user) #this function obviously not defined yet

しかし、コードcreate()は少しばかげており、if ラダーを必要とせず、User オブジェクトにまだないキーが追加された場合に失敗する、より良い方法があるかどうか疑問に思っています。お気に入り:

for attribute in kwargs.keys():
    if attribute in User:
        setattr(user, attribute, kwargs[attribute])
    else:
        raise Exception("blah")

そうすれば、これを独自の関数に入れることができます (うまくいけば、既に存在する場合を除きますか?) したがって、if はしごを何度も実行する必要がないため、このコードを変更せずにテーブル構造を変更できます。

助言がありますか?

4

3 に答える 3

2

私の提案は、これ以上単純化しないことです。任意の属性を割り当てると、重要なオブジェクト構造を踏む危険があります。

私が行う単純化の1つは.keys()、dictで使用するときにドロップすることです。封じ込めチェックと反復の両方で、すでにキーが使用されています。

...

考え直して、既知の安全な属性を含むクラス属性を持ち、関数内でこの属性をチェックsetattr()して、インスタンスで使用することができます。

于 2010-05-28T04:10:51.783 に答える
2

実際には、宣言型モジュール docsに記載されているように、宣言型基本クラスは、探している正確なコンストラクターを既に挿入しています。したがって、実行User(username="Carson", password="1234")するだけで、必要なことが実行されUser(something_not_an_attribute='foo')、例外が発生します。

于 2010-05-28T06:48:20.500 に答える
1

継承された属性をカバーする必要がない場合は、

def create(**kwargs):
    keys_ok = set(User.__dict__)
    user = User()
    for k in kwargs:
        if k in keys_ok:
            setattr(user, k, kwargs[k])

継承された属性をカバーする必要がある場合は、inspect.getmembers役立ちます(名前がアンダースコアで始まるメンバーや、この方法で設定できないことを確認したいメンバーを避けるためのカスタム述語を使用)。

set(kwargs) - set(keys_ok)空でない場合、つまり、渡された名前付き引数の一部を作成されたインスタンスで引数として設定create できない場合は、(少なくとも)警告を出すことも検討します。それは良いことではありません...!-)

于 2010-05-28T04:30:19.240 に答える