web-dev-qa-db-ja.com

sqlalchemyで1対多の関係を持つ新しいレコードを挿入する

私は、1対多の関係に関する モデルの宣言 のflask-sqlalchemyチュートリアルに従っています。サンプルコードは次のとおりです。

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address', backref='person',
                                lazy='dynamic')

class Address(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(50))
    person_id = db.Column(db.Integer, db.ForeignKey('person.id'))

今、私はそのようなモデルを使用してDBに新しいレコードを挿入する方法を疑問に思っています。コンストラクターinitが必要だと思いますが、その実装方法と使用方法を理解するのは困難です。ここでの主な問題は、PersonはAddressに依存し、AddressはPersonに対するForeignKeyを持っているため、Personを事前に知っている必要があるということです。

実行方法を理解してください。

前もって感謝します。

34
wanderlust

コンストラクタを記述する必要はありません。addressesインスタンスのPersonプロパティをリストとして扱うことができます:

a = Address(email='[email protected]')
p = Person(name='foo')
p.addresses.append(a)

または、アドレスのリストをPersonコンストラクターに渡すことができます

a = Address(email='[email protected]')
p = Person(name='foo', addresses=[a])

いずれの場合でも、次のようにPersonインスタンスのアドレスにアクセスできます。

db.session.add(p)
db.session.add(a)
db.session.commit()
print p.addresses.count() # 1
print p.addresses[0] # <Address object at 0x10c098ed0>
print p.addresses.filter_by(email='[email protected]').count() # 1
62
DazWorrall

場合によっては、「リストオブジェクトに属性_sa_instance_stateがない」などの例外があります。

a = Address(email='[email protected]')
p = Person(name='foo', addresses=a)

この例外を解決してください。

3
cyberra

このモデルを検討する際の最も重要なことは、このモデルが1対多の関係を持っているという事実を理解することです。つまり、1人の人が複数のアドレスを持ち、私たちのケースではそれらのアドレスをリストに保存します。

そのため、initを持つPersonクラスは次のようになります。

class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
    addresses = db.relationship('Address', backref='person',
                            lazy='dynamic')

    def __init__(self,id,name,addresses = []):
        self.id = id
        self.name = name
        self.addresses = addresses

そのため、このPersonクラスは、ID、名前、およびAddress型のオブジェクトを含むリストを必要とします。デフォルト値は空のリストであるようにしています。

それが役に立てば幸い。 :)

1
padfoot27