2013-05-10 18 views
4

我有如下2模型類:如何使用Flask-SQLAlchemy使用csv填充具有外鍵的模型?

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 '%[email protected]%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() 

拋出異常是:

File "data.py", line 55, in db.session.add(account)
File ".../local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 149, in do return getattr(self.registry(), name)(*args, **kwargs)
File ".../local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1397, in add self._save_or_update_state(state)
File ".../local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1415, in _save_or_update_state halt_on=self._contains_state):
File ".../local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1986, in cascade_iterator parent_dict, visited_states, halt_on))
File ".../local/lib/python2.7/site-packages/sqlalchemy/orm/properties.py", line 930, in cascade_iterator get_all_pending(state, dict_)
File ".../local/lib/python2.7/site-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'

PL。爲data.py恢復腳本中代碼的變化,即用於上傳具有Domain類的外鍵的EmailAccount模型的數據的腳本。我只想使用Flask-SQLAlchemy。

提取accounts.csv文件:

Email Account,legacy_username,password,full_name,quota,is_domain_admin,is_catch_all,disabled_login,disabled_delivery 
[email protected],,,,104857600,,,, 
[email protected],,,Internal,102400000,,,, 
[email protected],,,,102400000,,,, kishorepr,xyz.com,,,,209715200,,,, 

回答

2

當一行含有domain鍵,你取回域名,以獲取其關鍵,但你沒有你的row與域ID更新。

然後,當你這樣做:

account = EmailAccount(**row) 

row對象仍具有與域名相關的關鍵domain。由於您的EmailAccount類使用名稱domain作爲關係,所以db認爲它將獲得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() 
+0

@http://stackoverflow.com/users/1193366/morphyn感謝您的快速反應。你能告訴我代碼改變來解決這個問題嗎?在此先感謝 – user956424 2013-05-10 07:10:28

+0

您可以發佈您的帳戶csv文件的摘錄? – 2013-05-10 07:13:01

+0

http://stackoverflow.com/users/1193366/morphyn粘貼上面csv的摘錄。 – user956424 2013-05-10 07:23:56

相關問題