4

私は以下のように2つのモデルクラスを持っています:

class Domain(db.Model):
    __tablename__ = 'domain'
    id = db.Column(db.Integer, primary_key=True)
    domain_name = db.Column(db.String(30), unique=True)
    mailboxes = db.Column(db.Integer, default=0)

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        return '%s'  % self.domain_name


class EmailAccount(db.Model):
    __tablename__ = 'email_account'
    __table_args__ = (
        db.UniqueConstraint('username', 'domain_id', 
                            name='_uq_username_domain'),{}
    )
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(30))
    domain_id = db.Column(db.Integer, db.ForeignKey('domain.id'))
    domain = db.relationship('Domain', backref=db.backref('emailaccounts',
                            lazy='dynamic'))
    def __init__(self,**kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
         return  '%s@%s ' % (self.username, self.domain)

この例では、ここで必要な関連属性のみを追加しました。データの csv ファイルを読み取って、スクリプトを使用してモデルを作成したいと考えています。ドメイン テーブルのスクリプトは Flask-SQLAlchemy を使用してうまく機能しますが、emailaccount テーブルのスクリプトは例外をスローします。スクリプトは次のとおりです。

#Populate domains from csv
domain_file = "domain.csv"
csv_file = csv.DictReader(open(domain_file, 'rb'), delimiter=',')
for row in csv_file:
    #data type conversion from (csv)string before inserting to table
    for key, value in row.items():
          #some code omitted
        print key, value    
    domain = Domain(**row)
    db.session.add(domain)
    db.session.commit()

#Populate accounts from csv
accounts_file = "accounts.csv"
csv_file = csv.DictReader(open(accounts_file, 'rb'), delimiter=',')

for row in csv_file:
    mdomain_name = ''
    #data type conversion from (csv)string before inserting to table
    for key, value in row.items():
        print key, value
        if key == 'domain':
            mdomain = Domain.query.filter_by(domain_name = value).first()
            mdomain_name = mdomain.domain_name
            mdomain_id = mdomain.id
        if key == 'domain_id':
            value = mdomain_id
    account = EmailAccount(**row)
    db.session.add(account)
    db.session.commit()

スローされる例外は次のとおりです。

ファイル「data.py」、55 行目、db.session.add(account)
ファイル「.../local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py」、149 行目do return getattr(self.registry(), name)(*args, **kwargs)
ファイル ".../local/lib/python2.7/site-packages/sqlalchemy/orm/session.py"、1397 行目、 in add self._save_or_update_state(state)
ファイル ".../local/lib/python2.7/site-packages/sqlalchemy/orm/session.py"、1415 行目、_save_or_update_state halt_on=self._contains_state):
File ". ../local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py"、1986 行目、cascade_iterator の parent_dict、visited_states、halt_on))
ファイル ".../local/lib/python2.7/ site-packages/sqlalchemy/orm/properties.py"、930 行目、cascade_iterator get_all_pending(state,dict_)
ファイル ".../local/lib/python2.7/site-packages/sqlalchemy/orm/attributes.py"、761 行目、get_all_pending ret = [(instance_state(current), current)] AttributeError: 'str' object属性「_sa_instance_state」がありません

Pl。data.py のスクリプト、つまりドメイン クラスの外部キーを持つ EmailAccount モデルのデータをアップロードするスクリプトのコードの変更を元に戻します。Flask-SQLAlchemy のみを使用したい。

accounts.csv ファイルの抜粋:

Email Account,legacy_username,password,full_name,quota,is_domain_admin,is_catch_all,disabled_login,disabled_delivery
info@abc.com,,,,104857600,,,,
internal@abc.com,,,Internal,102400000,,,,
kiran.rs@abc.com,,,,102400000,,,, kishorepr,xyz.com,,,,209715200,,,,
4

1 に答える 1

2

行にdomainキーが含まれている場合、ドメインを取得してそのキーを取得しますrowが、ドメイン ID で更新しません。

次に、次のことを行います。

account = EmailAccount(**row)

rowオブジェクトにはdomain、ドメイン名に関連付けられたキーがまだあります。EmailAccountクラスは関係の名前を使用するためdomain、データベースはDomain、実際にはstring(名前)を取得しているときにオブジェクトを取得すると考えています。そのため、エラーが発生しますAttributeError: 'str' object has no attribute '_sa_instance_state'

更新:これはうまくいくはずです

for row in csv_file:
    account_values = {}
    for key, value in row.items():
        if key == 'domain':
            mdomain = Domain.query.filter_by(domain_name = value).first()
            account_values['domain'] = mdomain
        else:
            account_values[key] = value
    account = EmailAccount(account_values)
    db.session.add(account)
    db.session.commit()
于 2013-05-10T06:55:43.260 に答える