2015-11-11 1 views
2

Я проверил документы и это довольно неопределенно, как метод is_accessible должен быть реализован.flask-admin is_accessible use

Вот что документы опоки админ показали

class MicroBlogModelView(sqla.ModelView): 

    def is_accessible(self): 
     return login.current_user.is_authenticated() 

    def inaccessible_callback(self, name, **kwargs): 
     # redirect to login page if user doesn't have access 
     return redirect(url_for('login', next=request.url)) 

, что я не получаю, хотя, как вы это называете это он вызывается автоматически, или вы должны назвать это сами, как это:

@expose("/", methods=["GET", "POST"]) 
    def home(self): 
     if self.is_accesible(): 
      return super().index() 
     else: 
      return self.login() 

    def is_accesible(self): 
     return current_user.is_authenticated and "admin" in current_user.role 

, потому что это было бы чертовски повторяющимся поставить галочку

if self.is_accesible(): 
       return super().index() 

если бы мы имели ли t просмотров admin. Так как же мы его реализуем? Документах показал, как поместить его в модели, но не так, как реализовать это на ваши взгляды

+1

У меня тоже есть вопросы о неосновных функций колба-администратора, но замечаю, что ответы на [тег] (http://stackoverflow.com/questions/tagged/flask-admin) являются низкими. Позор, поскольку у него большой потенциал. На некоторые вопросы выдается ответ на [вопрос трекера] (https://github.com/flask-admin/flask-admin/issues/), но он попал или промахнулся. – zx81

+1

@ zx81 В большинстве вопросов, связанных с флягой, я оказался в ответе. в некоторых документах отсутствует информация. Я серьезно рассматривает Джанго для изменения – Zion

ответ

5

Смотрите пример кода ниже - большая часть кода взят дословно из Quokka CMS

Определить Roled подмешать, который обрабатывает def is_accessible(self) и def _handle_view(self, name, *args, **kwargs).

В примере я использовал функцию, def is_accessible(roles_accepted=None, user=None), для обработки логики определения допустимости роли.

Определение класса вида с sqla ModelView и Roled подмешать, а именно:

class AdminView(Roled, ModelView): 

    def __init__(self, *args, **kwargs): 
     self.roles_accepted = kwargs.pop('roles_accepted', list()) 
     super(AdminView, self).__init__(*args, **kwargs) 

Выведите свои модели вида из этого класса:

class UserView(AdminView): 
    form_excluded_columns = ('password') 

class RoleView(AdminView): 
    pass 

class PostView(AdminView): 
    pass 

Добавить свои взгляды на класс администратора в нормальном но передайте список разрешенных имен ролей с помощью ключевого слова roles_accepted:

admin.add_view(UserView(model=User, session=db.session, category='Account', name='Users', roles_accepted=['admin'])) 
admin.add_view(RoleView(model=Role, session=db.session, category='Account', name='Roles', roles_accepted=['admin'])) 
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Editor Only)', roles_accepted=['editor'])) 
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Admins & Editors)', endpoint="post_special", roles_accepted=['editor', 'admin'])) 

См. Полный код одного файла ниже. Это было проверено под Python 2.7.9, 0.10.1 Колбы, колба-админ 1.1.0, колба-безопасность 1.7.4 и колбовой Войти 0.2.11

from datetime import datetime 
from flask import Flask, redirect, current_app 
from flask.ext.admin import Admin 
from flask.ext.admin.contrib.sqla import ModelView 
from flask.ext.admin.menu import MenuLink 
from flask.ext.security import (
    current_user, 
    url_for_security, 
    UserMixin, 
    RoleMixin, 
    SQLAlchemyUserDatastore, 
    Security 
) 
from flask.ext.security.utils import encrypt_password 
from flask.ext.sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
app.config['DEBUG'] = True 
app.config['SECRET_KEY'] = 'super-secret' 
app.config['SECURITY_PASSWORD_HASH'] = 'pbkdf2_sha512' 
app.config['SECURITY_PASSWORD_SALT'] = '16a0af319890f662055ba10aecff37e7e033db3fba737e55' 
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = 'email' 

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' 
app.config['SQLALCHEMY_ECHO'] = True 
db = SQLAlchemy(app) 


class Role(db.Model, RoleMixin): 
    __tablename__ = 'roles' 

    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.Unicode(length=64), unique=True) 
    description = db.Column(db.Unicode(length=255), nullable=True) 

    def __unicode__(self): 
     return u"{name} ({role})".format(name=self.name, role=self.description or 'Role') 

user_to_role = db.Table('user_to_role', 
    db.Column('user_id', db.Integer(), db.ForeignKey('users.id')), 
    db.Column('role_id', db.Integer(), db.ForeignKey('roles.id'))) 


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

    id = db.Column(db.Integer, primary_key=True) 

    first_name = db.Column(db.Unicode(length=255), nullable=False) 
    last_name = db.Column(db.Unicode(length=255), nullable=False) 

    email = db.Column(db.Unicode(length=254), unique=True, nullable=True) 
    password = db.Column(db.Unicode(length=255), nullable=False) 
    active = db.Column(db.Boolean(), default=False) 

    roles = db.relationship('Role', secondary=user_to_role, backref=db.backref('users', lazy='select')) 

    def __unicode__(self): 
     return u"{first_name} ({last_name})".format(first_name=self.first_name, last_name=self.last_name) 


class Post(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    title = db.Column(db.String(255)) 
    content = db.Column(db.Text, nullable=False) 

    def __unicode__(self): 
     return self.title 


def get_current_user(): 
    from flask.ext.security import current_user 
    try: 
     return User.objects.get(id=current_user.id) 
    except Exception as e: 
     # logger.warning("No user found: %s", str(e)) 
     return current_user 


def is_accessible(roles_accepted=None, user=None): 
    user = user or get_current_user() 
    # uncomment if "admin" has access to everything 
    # if user.has_role('admin'): 
    #  return True 
    if roles_accepted: 
     accessible = any(
      [user.has_role(role) for role in roles_accepted] 
     ) 
     return accessible 
    return True 


class Roled(object): 

    def is_accessible(self): 
     roles_accepted = getattr(self, 'roles_accepted', None) 
     return is_accessible(roles_accepted=roles_accepted, user=current_user) 

    def _handle_view(self, name, *args, **kwargs): 
     if not current_user.is_authenticated(): 
      return redirect(url_for_security('login', next="/admin")) 
     if not self.is_accessible(): 
      # return self.render("admin/denied.html") 
      return "<p>Access denied</p>" 

class AdminView(Roled, ModelView): 

    def __init__(self, *args, **kwargs): 
     self.roles_accepted = kwargs.pop('roles_accepted', list()) 
     super(AdminView, self).__init__(*args, **kwargs) 


class UserView(AdminView): 
    form_excluded_columns = ('password') 


class RoleView(AdminView): 
    pass 


class PostView(AdminView): 
    pass 


# Setup Flask-Security 
security = Security(app, SQLAlchemyUserDatastore(db, User, Role)) 

@app.route('/') 
def index(): 
    _login = url_for_security('login', next="/admin") 
    _logout = url_for_security('logout', next="/admin") 
    return ''' 
     <a href="/admin/">Click me to get to Admin!</a><br> 
     <a href="{login}">Click me to get to login!</a><br> 
     <a href="{logout}">Click me to get to logout!</a> 
     '''.format(login=_login, logout=_logout) 


# Create admin 
admin = Admin(app, name='Admin') 
admin.add_view(UserView(model=User, session=db.session, category='Account', name='Users', roles_accepted=['admin'])) 
admin.add_view(RoleView(model=Role, session=db.session, category='Account', name='Roles', roles_accepted=['admin'])) 
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Editor Only)', roles_accepted=['editor'])) 
admin.add_view(PostView(model=Post, session=db.session, category='Blog', name='Posts (Admins & Editors)', endpoint="post_special", roles_accepted=['editor', 'admin'])) 
admin.add_link(MenuLink(name='Public Website', category='', url='/')) 


def build_db(): 
    users = [ 
     { 
      'first_name': 'Super', 
      'last_name': 'User', 
      'email': '[email protected]', 
      'active': True, 
      'password' : encrypt_password('password'), 
      'roles': ['admin'] 
     }, 
     { 
      'first_name': u'Post', 
      'last_name': u'Editor', 
      'email': '[email protected]', 
      'active': True, 
      'password': encrypt_password('password'), 
      'roles': ['editor'] 
     }, 

    ] 

    posts = [ 
     { 
      'title': "de Finibus Bonorum et Malorum - Part I", 
      'content': "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut" 
     }, 
     { 
      'title': "de Finibus Bonorum et Malorum - Part II", 
      'content': "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque" 
     }, 
     { 
      'title': "de Finibus Bonorum et Malorum - Part III", 
      'content': "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium" 
     } 
    ] 

    db.drop_all() 
    db.create_all() 

    security = current_app.extensions.get('security') 

    security.datastore.create_role(name=u"admin", description=u'Administers the system') 
    security.datastore.create_role(name=u"editor", description=u'Can edit posts') 

    for user in users: 
     roles = user.pop('roles') 
     user_db = security.datastore.create_user(**user) 
     for role_name in roles: 
      role_from_db = security.datastore.find_role(role_name) 
      security.datastore.add_role_to_user(user_db, role_from_db) 
     security.datastore.activate_user(user_db) 
     user_db.confirmed_at = datetime.now() 

    security.datastore.commit() 

    for row in posts: 
     post = Post(**row) 
     db.session.add(post) 

    db.session.commit() 


@app.before_first_request 
def create_user(): 
    build_db() 

if __name__ == '__main__': 
    app.run(debug=True) 
+0

'класса AdminView (Roled, ModelView): Защиту __init __ (самоповреждения, * Args ** kwargs): self.roles_accepted = kwargs.pop ('roles_accepted', список()) super (AdminView, self) .__ init __ (* args, ** kwargs) ' этот блок кода прямо здесь. где супер? на 'ModelView'? это первый раз, когда я столкнулся с множественным наследованием с помощью 'super' – Zion

+1

@Zion.Правильно - это вызов метода sqla.ModelView .__ init__'. – pjcunningham

+0

wow, очевидно, делает это, получится довольно волосатым, если оба родительских класса имеют один и тот же метод при вызове super. Я до сих пор не встречал этого. – Zion

1

Он вызывается автоматически каждый раз, когда вид доступен , Вы можете проверить это, используя инструкцию печати. Запустите приложение и посмотрите в окне консоли.

class MicroBlogModelView(sqla.ModelView): 

def is_accessible(self): 
    print "Called ME!!!!!!!!" 
    return login.current_user.is_authenticated() 

def inaccessible_callback(self, name, **kwargs): 
    # redirect to login page if user doesn't have access 
    return redirect(url_for('login', next=request.url))