2017-09-01 59 views
0

我有一個我想要初始化的模型,例如SomeModel(name='george', password='whatever')Flask-SQLAlchemy:在將模型實例提交給數據庫之前,如何調用實例方法?

將數據提交給數據庫之前,我想調用另一個方法(我們將其稱爲gen_password_hash)來創建密碼的散列版本,並將其設置爲模型實例上的屬性。

所以我希望這發生在實例化之後,但在提交到數據庫之前。

更新

我想看看,如果我可以在我的模型定義__init__功能做到這一點。

def __init__(self, **kwargs): 
    self.set_pass(kwargs.pop('password')) 
    super(User, self).__init__(**kwargs) 
    self.generate_email_address_confirmation_token() 

這是回溯試圖除去/重新創建除其他事項外表重置我的應用程序時,我得到:

Traceback (most recent call last): 
    File "main.py", line 7, in <module> 
    import gg.cli 
    File "/home/blaine/freelance/myproject/gg/cli/__init__.py", line 183, in <module> 
    reset_all() 
    File "/home/blaine/freelance/myproject/gg/cli/__init__.py", line 164, in reset_all 
    load_test_data() 
    File "/home/blaine/freelance/myproject/gg/cli/__init__.py", line 51, in load_test_data 
    admin=True) 
    File "<string>", line 4, in __init__ 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/sqlalchemy/orm/state.py", line 414, in _initialize_instance 
    manager.dispatch.init_failure(self, args, kwargs) 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__ 
    compat.reraise(exc_type, exc_value, exc_tb) 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/sqlalchemy/util/compat.py", line 187, in reraise 
    raise value 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/sqlalchemy/orm/state.py", line 411, in _initialize_instance 
    return manager.original_init(*mixed[1:], **kwargs) 
    File "/home/blaine/freelance/myproject/gg/users.py", line 67, in __init__ 
    self.generate_email_address_confirmation_token() 
    File "/home/blaine/freelance/myproject/gg/users.py", line 71, in generate_email_address_confirmation_token 
    token.update(self.email_address.encode() + current_app.secret_key + \ 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/werkzeug/local.py", line 347, in __getattr__ 
    return getattr(self._get_current_object(), name) 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/werkzeug/local.py", line 306, in _get_current_object 
    return self.__local() 
    File "/home/blaine/freelance/myproject/lib/python3.4/site-packages/flask/globals.py", line 51, in _find_app 
    raise RuntimeError(_app_ctx_err_msg) 
RuntimeError: Working outside of application context. 

This typically means that you attempted to use functionality that needed 
to interface with the current application object in a way. To solve 
this set up an application context with app.app_context(). See the 
documentation for more information. 

我用this question for reference

+0

這將取決於這個'gen_password_hash'是如何定義的。如果它是在'SomeModel'類中定義的,那麼你應該能夠實例化這個類,然後在提交之前調用方法'.gen_password_hash'。但是如果它是在模型外部定義的函數,那麼你需要像'user = SomeModel(name ='george',password ='whatever'); user.hashed_pwd = gen_password_hash(user.password); db.session.add(用戶); db.session.commit()'。還要確保'hashed_pwd'是你的模型中定義的一列,如果你有第二個場景。 – Abdou

+0

我明白了。這樣可行。我希望使用'__init__'方便地包裝所有這些東西,但是我收到錯誤,說我在應用程序上下文之外工作。 –

+0

隨時分享導致錯誤的代碼,我或其他人會很樂意提供修復。你絕對可以使用__init__來獲得密碼散列。 – Abdou

回答

0

以下是我對你要做什麼的解釋。您想創建一個靜態方法,將給定的字符串密碼轉換爲哈希密碼。顯然python的hash不是密碼哈希函數,所以我會建議使用其他更一致和可靠的東西。這種散列方法可以在應用程序中User模型的初始化過程中使用。這意味着每次使用用戶名,電子郵件和密碼創建用戶時,該密碼首先被散列,然後將其作爲接下來的User對象的屬性。看看下面的插圖:

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 


app = Flask(__name__) 
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' 
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 
db = SQLAlchemy(app) 


class User(db.Model): 
    __tablename__ = 'users' 

    id = db.Column(db.Integer, primary_key=True) 
    username = db.Column(db.String(80), unique=True) 
    email = db.Column(db.String(120), unique=True) 
    password = db.Column(db.String(36)) 

    def __init__(self, username, email, password): 
     self.username = username 
     self.email = email 
     self.password = self.generate_pwd_hash(password) 

    @staticmethod 
    def generate_pwd_hash(pwd): 
     """ 
     This is where you define how 
     to hash the user's password. 
     """ 
     return str(hash(pwd)) # This is, of course, not the way to hash a password 


db.create_all() 

user = User(username='george', 
      email='[email protected]', 
      password='whatever') 

try: 
    db.session.add(user) 
    db.session.commit() 
except: 
    print("This username must already exist.") 
相關問題