2017-05-04 81 views
0

在我的應用程序中努力實現Flask-Security。我在創建默認管理員帳戶時出錯。我跟着示例代碼非常密切和上午從而爲錯誤的來源很困惑:TypeError: __init__() got an unexpected keyword argument 'password'Flask-Security init:意外的關鍵字參數'password'

__init__.py

from flask import Flask 
from flask_sqlalchemy import SQLAlchemy 
from flask_migrate import Migrate 
from flaskext.markdown import Markdown 
from flask_uploads import UploadSet, configure_uploads, IMAGES 
from flask_security import Security, SQLAlchemyUserDatastore, utils 
from flask_mail import Mail 
import private 

app = Flask(__name__) 
app.config.from_object('settings') 
db = SQLAlchemy(app) 
mail = Mail(app) 

# migrations 
migrate = Migrate(app, db) 

# markdown 
md = Markdown(app, extensions=['fenced_code', 'tables']) 

# images 
uploaded_images = UploadSet('images', IMAGES) 
configure_uploads(app, uploaded_images) 

try: 
    # importing in a try to avoid import conflict, what's the better way?: 
    from user.models import User, Role  
    # Setup Flask-Security 
    user_datastore = SQLAlchemyUserDatastore(db, User, Role) 
    security = Security(app, user_datastore) 
except Exception as ee: 
    pass 


from roster import views 
from sentence import views 
from blog import views 
from user import views 

@app.before_first_request 
def before_first_request(): 

    # Create the Roles "admin" and "end-user" -- unless they already exist 
    user_datastore.find_or_create_role(name='admin', description='Administrator') 
    user_datastore.find_or_create_role(name='end-user', description='End user') 

    # Create two Users for testing purposes -- unless they already exists. 
    # In each case, use Flask-Security utility function to encrypt the password. 
    encrypted_password = utils.encrypt_password(private.STARTING_ADMIN_PASS) 
    if not user_datastore.get_user('[email protected]'): 
     user_datastore.create_user(email='[email protected]', password=encrypted_password) 

    db.session.commit() 

    user_datastore.add_role_to_user('[email protected]', 'admin') 
    db.session.commit() 

user.models

from my_app import db 
from blog.models import Post 
from sentence.models import Sentence 
from roster.models import Roster 
from datetime import datetime 
import datetime 
from flask_security import UserMixin, RoleMixin 

# Helper table for a many-to-many relationship 
roles_users = db.Table('roles_users', 
     db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), 
     db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) 

class Role(db.Model, RoleMixin): 
    id = db.Column(db.Integer(), primary_key=True) 
    name = db.Column(db.String(80), unique=True) 
    description = db.Column(db.String(255)) 

class User(db.Model, UserMixin): 
    # general variables 
    id = db.Column(db.Integer, primary_key=True) 
    first_name = db.Column(db.String(155)) 
    last_name = db.Column(db.String(155)) 
    email = db.Column(db.String(255), unique=True) 
    password = db.Column(db.String(255)) 
    active = db.Column(db.Boolean()) 
    confirmed_at = db.Column(db.DateTime()) 

    # relations 
    roles = db.relationship('Role', secondary=roles_users, 
          backref=db.backref('users', lazy='dynamic')) 
    posts = db.relationship('Post', backref='user', lazy='dynamic') 
    sentences = db.relationship('Sentence', backref='user', lazy='dynamic') 

    def __init__(self, name, email): 
     # create a roster 
     roster = Roster("default", self.email) 
     db.session.add(roster) 
     db.session.commit() 

    def __repr__(self): 
     return '<User %r>' % self.username 

    # __str__ is required by Flask-Admin (not using?), so we can have human-readable values for the Role when editing a User. 
    # If we were using Python 2.7, this would be __unicode__ instead. 
    def __str__(self): 
     return self.name 

    # __hash__ is required to avoid the exception TypeError: unhashable type: 'Role' when saving a User 
    def __hash__(self): 
     return hash(self.name) 

回溯

Traceback (most recent call last): 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1994, in __call__ 
    return self.wsgi_app(environ, start_response) 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app 
    response = self.handle_exception(e) 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception 
    reraise(exc_type, exc_value, tb) 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise 
    raise value 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app 
    response = self.full_dispatch_request() 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1607, in full_dispatch_request 
    self.try_trigger_before_first_request_functions() 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask/app.py", line 1654, in try_trigger_before_first_request_functions 
    func() 
    File "/home/ubuntu/workspace/my_app/__init__.py", line 51, in before_first_request 
    user_datastore.create_user(email='[email protected]', password=encrypted_password) 
    File "/home/ubuntu/workspace/my_app/venv/lib/python3.6/site-packages/flask_security/datastore.py", line 167, in create_user 
    user = self.user_model(**kwargs) 
TypeError: __init__() got an unexpected keyword argument 'password' 
+2

請[編輯]包括一個[MCVE。什麼是完整的追溯,不只是最後的錯誤? – davidism

+0

我不知道這個錯誤是否是'Try:'的結果。我的'db'對象是否應該在不同的文件中實例化?這意味着我不需要從模型中導入my_app。如果我不需要'my_app'和它的'__init__'方法,我可以自由地在'__init__'中'import user.models',而不必費心使用'Try:'。 – dadiletta

+0

我已經修復了導入衝突,感謝[此問題](http://stackoverflow.com/questions/43812329/python-import-conflict-with-flask-security)。但是,我仍然遇到同樣的錯誤。 – dadiletta

回答

0

如果你看一下瓶,安全的datastore.py你可以看到什麼呢.create_user()

def create_user(self, **kwargs): 
    """Creates and returns a new user from the given parameters.""" 
    kwargs = self._prepare_create_user_args(**kwargs) 
    user = self.user_model(**kwargs) 
    return self.put(user) 

它只是試圖實例給出User模型。要修復,調整__init__方法在User模型來處理一個password元素,像這樣:

def __init__(self, **kwargs): 
    self.password = kwargs['password'] 
    self.email = kwargs['email'] 
    if kwargs.get('first_name', False): 
     self.first_name = kwargs['first_name'] 
     self.last_name = kwargs['last_name'] 
    #roster stuff... 
相關問題