web-dev-qa-db-ja.com

SQLalchemy AttributeError: 'str'オブジェクトには属性 '_sa_instance_state'がありません

SQLAlchemy + Pythonを使用してデータベースにアイテムを追加しようとしていますが、エラーが発生し続けます。

私のdatabase_setup.py:

class company(Base):
    __tablename__ = 'company'
    compID = Column(Integer, primary_key = True)
    name = Column(String(80), nullable = False)

class item(Base):
    __tablename__ = 'items'
    itemID = Column(Integer, primary_key = True)
    name = Column(String(80), nullable = False)
    category = Column(String(250))
    description = Column(String(250))
    price = Column(String(8))
    compID = Column(Integer, ForeignKey('company.compID'))
    company = relationship(company)

sqlalchemyを端末にインポートした後、挿入するアイテムを定義します。

JawboneUP3 = item(
    itemID="1",
    name="Jawbone UP3",
    description="The latest UP!", 
    category="tracker",
    price="$174.99",
    company="Jawbone"
)

追加してコミットするセッションを描画します。

session.add(JawboneUP3)
session.commit()

送信すると、このエラーが発生し続けます。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 1399, in add
    self._save_or_update_state(state)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/session.py", line 1417, in _save_or_update_state
    halt_on=self._contains_state):
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/mapper.py", line 2037, in cascade_iterator
    parent_dict, visited_states, halt_on))
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/properties.py", line 932, in cascade_iterator
    get_all_pending(state, dict_)
  File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 761, in get_all_pending
   ret = [(instance_state(current), current)]
AttributeError: 'str' object has no attribute '_sa_instance_state'

会社のテーブルに「Jawbone」オブジェクトを追加しました。これは、「JawboneUP3」が関連付けられる必要があることを理解しています。このオブジェクトは、Webサーバースクリプトで有効にしたブラウザーフォームから正しく追加されました。端末から直接アイテムを追加できると思います。

17
mleafer

問題は、関連する会社のスキーマをどのように定義しているかにあると思います。

JawboneUP3 = item(itemID = "1", name = "Jawbone UP3", description = "The latest UP!", 
                  category = "tracker", price = "$174.99", company = "Jawbone")
                                                           # HERE^

itemコンストラクタはcompanyインスタンスを想定していますが、文字列値を渡しています。修理する:

JawboneUP3 = item(itemID="1", 
                  name="Jawbone UP3", 
                  description="The latest UP!", 
                  category="tracker", 
                  price="$174.99", 
                  company=company(name="Jawbone"))
29
alecxe

まず、Pythonでクラスを定義するときは、次のように名前を大文字で始めることをお勧めします。

class Company(Base):
    __tablename__ = 'company'
    compID = Column(Integer, primary_key = True)
    name = Column(String(80), nullable = False)

class Item(Base):
    __tablename__ = 'items'
    itemID = Column(Integer, primary_key = True)
    name = Column(String(80), nullable = False)
    category = Column(String(250))
    description = Column(String(250))
    price = Column(String(8))
    compID = Column(Integer, ForeignKey('company.compID'))
    company = relationship(company)

とはいえ、コードがエラーをスローするのはそのためではありません。 :)

理由

Itemコンストラクターは、変数Companyの値として渡されるオブジェクトcompanyのインスタンスを期待します

解決策1:Jawbone会社がデータベースに存在しない

ここで@alecxeの答えは有効です。

あなたのコードを次のように置き換える必要があります:

JawboneUP3 = Item(itemID="1", 
                  name="Jawbone UP3", 
                  description="The latest UP!", 
                  category="tracker", 
                  price="$174.99", 
                  company=company(name="Jawbone"))

このオブジェクトをセッションに追加して変更をコミットすると、実際にはデータベースに2つのエントリが作成されます。

  • 「Jawbone UP3」という名前のアイテムエントリ
  • companyデータベース内の行、「Jawbone」という名前の会社

解決策2:Jawbone会社がデータベースに存在する

ここで、テーブル「company」から会社Jawboneをフェッチし、次のようにItemコンストラクターに引数として渡す必要があります。

jawbone = session.query(Company).filter_by(name="Jawbone").first()

JawboneUP3 = Item(itemID="1", 
                  name="Jawbone UP3", 
                  description="The latest UP!", 
                  category="tracker", 
                  price="$174.99", 
                  company=jawbone)

sessionの部分をチェック this

4
Tiwtiw
from flask import Flask
from flask import request,redirect,render_template
from flask_sqlalchemy import SQLAlchemy

app=Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students1.sqlite3'
db=SQLAlchemy(app)

class Categ(db.Model):
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(100))
    product=db.relationship('Product',backref='owner',lazy=True)

class Product(db.Model):
    id=db.Column(db.Integer,primary_key=True)
    pname=db.Column(db.String(100))
    price=db.Column(db.Integer)
    categ_id=db.Column(db.Integer,db.ForeignKey('categ.id'))

@app.route('/')
def home():
    return 'home'

@app.route('/post',methods=['POST','GET'])
def Productform():
    ob=Categ.query.all()
    if request.method=='POST':
        owner=request.form['ca']
        user = Categ.query.filter_by(name=owner).first()

        user=Product(pname=request.form['pname'],price=request.form['price'],owner=user)
        db.session.add(user)
        db.session.commit()

        return 'submit'

    return render_template('product.html',ob=ob)



@app.route('/categ',methods=['POST','GET'])
def Categoryform():
    if request.method=='POST':
        user=Categ(name=request.form['cname'])
        db.session.add(user)
        db.session.commit()

        return 'submit'

    return render_template('categ.html')


if __name__ == '__main__':
   app.run(debug=True)
   db.create_all()
0
Fauzan khan