2016-08-25 46 views
3

我正在写一些帐户创建代码,并试图捕获特定的sqlalchemy异常,以便当用户使用已经与现有帐户关联的电子邮件注册帐户时,我可以反馈相应的错误消息。为什么我得到一个sqlalchemy.exc.ProgrammingError而不是sqlalchemy.exc.IntegrityError?

我期待在发生这种情况时得到一个IntegrityError,但我却得到一个ProgrammingError。我可以愉快地抓住ProgrammingError,但我想明白为什么我没有得到我期望的。

我剪下来为清晰起见,模型和代码,但该模型的样子:

from service import db 
from sqlalchemy import Index 

class UserProfile(db.Model): 
user_id = db.Column(db.String(255), nullable=False, primary_key=True) 
email = db.Column(db.String(255), nullable=False) 

def __init__(self, account_data): 
    self.user_id = account_data['userId'] 
    self.email = account_data['email'].lower() 

def __repr__(self): 
    return 'UserID-{}, Email-{}'.format(self.user_id,self.email)                    

Index('idx_email', UserProfile.email, unique=True) 

和代码的主位的样子:

@app.route('/create_account', methods=['POST']) 
def create_account(): 

account_data = request.get_json() 

account_details = UserProfile(account_data) 
try: 
    db.session.add(account_details) 
    db.session.flush() 

    # do stuff 

    db.session.commit() 

except ProgrammingError as err: 
    db.session.rollback() 
    if "duplicate key value violates unique constraint \"idx_email\"" in str(err): 
     LOGGER.error('Email address already in use!' 

所以,如果我在后一些JSON例如:

{ 
    "userId": "Fred", 
    "email": "[email protected]" 
} 

然后用不同的userId再次发布,但相同的电子邮件:

{ 
    "userId": "Bob", 
    "email": "[email protected]" 
} 

我希望第二个帖子引发IntegrityError但我看到它提出一个ProgrammingError:

sqlalchemy.exc.ProgrammingError: (pg8000.core.ProgrammingError) 
('ERROR', 
'23505', 
'duplicate key value violates unique constraint "idx_email"', 
'Key (email)=([email protected]) already exists.', 
'public', 
'user_profile', 
'idx_email', 
'nbtinsert.c', 
'406', 
'_bt_check_unique', '', '') 
[SQL: 'INSERT INTO user_profile (user_id, email) VALUES (%s, %s)'] 
[parameters: ('Bob', '[email protected]')] 

我缺少什么?

回答

3

不幸的是,当涉及到DBAPI错误时,SQLAlchemy仅包装底层dbapi兼容库引发的异常。

也就是说,SQLAlchemy的提出了一个ProgrammingError特别是仅因为pg8000选择了养ProgrammingError

如果您一直在使用psycopg2来管理您的基础连接,那么您的错误将显示为IntegrityError(如预期的那样)。

根据pg8000 documentation,它永远不会产生IntegrityError。实际上它不会引起以下任何一种情况:

  • IntegrityError;
  • DataError;
  • DatabaseError;
  • OperationalError;

这里的教训是,当涉及到数据库级错误时,不能保证SQLAlchemy将在不同的dbapi连接器中抛出的类型。

相关问题