flask-admin:如何只允许超级用户查看指定的表列?

时间:2017-03-01 08:48:14

标签: flask flask-sqlalchemy flask-admin

我已经使用名为 Project 的表格构建了一个应用程序,该表存储在sqlite中,我希望只允许超级用户可以查看批准< / strong>创建,编辑数据时的列。

&#34;类项目&#34; 中检索项目数据,并添加了 &#34;类ProjectView&#34;

中的if current_user.has_role('superuser')
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_security import SQLAlchemyUserDatastore, current_user,UserMixin,        
     RoleMixin
from flask_admin.contrib import sqla

 # Create Flask application
 app = Flask(__name__)
 app.config.from_pyfile('config.py')
 db = SQLAlchemy(app)

 # Define models
 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))

     def __str__(self):
         return self.name

 class User(db.Model, UserMixin):
     id = db.Column(db.Integer, primary_key=True)
     email = db.Column(db.String(255), unique=True)
     password = db.Column(db.String(255))
     roles = db.relationship('Role', secondary=roles_users,
                        backref=db.backref('users', lazy='dynamic'))

     def __str__(self):
         return self.email

 class Project(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    team = db.Column(db.Unicode(64))
    project_name = db.Column(db.Unicode(128))
    approve = db.Column(db.Boolean())

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


  # Create customized model view class
 class MyModelView(sqla.ModelView):

     def is_accessible(self):
        if not current_user.is_active or not current_user.is_authenticated:
            return False

        if current_user.has_role('superuser'):
            return True

        return False

     def _handle_view(self, name, **kwargs):
        if not self.is_accessible():
            if current_user.is_authenticated:
                # permission denied
               abort(403)
        else:
            # login
            return redirect(url_for('security.login', next=request.url))

 class ProjectView(sqla.ModelView):

    def is_accessible(self):
        if not current_user.is_active:
            return False
        else:
            return True

    def _handle_view(self, name, **kwargs):
        if not self.is_accessible():
            if current_user.is_authenticated:
                # permission denied
               abort(403)
            else:
               if current_user.has_role('superuser'):
                 form_create_rules = [
                 rules.FieldSet(('team'), 'Personal Info'),
                 rules.Header('Project Info'),
                 rules.Field('project_name'),
                 'approve',
                 rules.Container('rule_demo.wrap', rules.Field('notes'))
                 ]

             else: 
                 form_create_rules = [
                 rules.FieldSet(('team'), 'Personal Info'),
                 rules.Header('Project Info'),
                 rules.Field('project_name'),
                 #'approve',
                 rules.Container('rule_demo.wrap', rules.Field('notes'))
                 ]
             form_edit_rules = form_create_rules

             create_template = 'rule_create.html'
             edit_template = 'rule_edit.html'

    @app.route('/')
    def index():
      return render_template('index.html')

    # Create admin
    admin = flask_admin.Admin(
          app,
          'Release Control System',
          # log in success page
          base_template='my_master.html',   
          template_mode='bootstrap3',
        )

   # Add model views
   admin.add_view(MyModelView(Role, db.session))
   admin.add_view(MyModelView(User, db.session))
   admin.add_view(ProjectView(Project, db.session))

但它仍然不起作用,所有用户仍然可以查看批准列。好心提醒。提前谢谢。

4 个答案:

答案 0 :(得分:6)

您可以使用BaseModelView.column_list属性指定动态计算的可访问列表,只需将其设为属性即可。然而不同的&#34;领域&#34; ModelView的属性在应用程序启动时被缓存,因此您需要覆盖它们的缓存:

from flask import has_app_context

class ProjectView(sqla.ModelView):
    @property
    def _list_columns(self):
        return self.get_list_columns()

    @_list_columns.setter
    def _list_columns(self, value):
        pass

    @property
    def column_list(self):
        if not has_app_context() or current_user.has_role('superuser'):
            return ['team', 'project_name', 'approve']
        else:
            return ['team', 'project_name']
column_list不可用时,在应用程序初始化期间使用

current_user属性。使用flask.has_app_context()方法检查此状态,并在启动时将应用程序的完整列表传递给应用程序。

如果您需要指定不同的列进行编辑,则需要form_rules属性(您已在问题中使用过它们):

from flask_admin.form import rules

class ProjectView(sqla.ModelView):
    @property
    def _form_edit_rules(self):
        return rules.RuleSet(self, self.form_rules)

    @_form_edit_rules.setter
    def _form_edit_rules(self, value):
        pass

    @property
    def _form_create_rules(self):
        return rules.RuleSet(self, self.form_rules)

    @_form_create_rules.setter
    def _form_create_rules(self, value):
        pass

    @property
    def form_rules(self):
        form_rules = [
            rules.FieldSet(('team',), 'Personal Info'),
            rules.Header('Project Info'),
            rules.Field('project_name')
        ]
        if not has_app_context() or current_user.has_role('superuser'):
            form_rules.append('approve')
        form_rules.append(rules.Container('rule_demo.wrap', rules.Field('notes')))
        return form_rules

此外,您无需使用_handle_view将用户重定向到登录页面。为此,使用了BaseView.inaccessible_callback方法:

def inaccessible_callback(self, name, **kwargs):
    if current_user.is_authenticated:
        abort(403)
    else:
        return redirect(url_for('security.login', next=request.url))

答案 1 :(得分:0)

connection.Open();
var cmd = new SqlCommand("SELECT TOP 1000 [Id] ,[Name]  FROM [SomeBase]", connection); //Here
context.MaxID = 100;
int en = 5; //Maximum number of rows in the slice
int iter = 0; //Iterator for each single row in the slice
try
{
    SqlDataReader reader = cmd.ExecuteReader();
    if(reader.HasRows)
    {
        while (iter < en) //I need 1-5 rows in first iteration, 6-10 in second...
        {
            iter++;
            reader.Read();
            context.TextLog += String.Format("{0}\t{1}\n",
            reader.GetInt64(0), 
            reader.GetString(1));
        }
    }
    reader.Close();
}

enter image description here

enter image description here

enter image description here

答案 2 :(得分:0)

class ProjectView(sqla.ModelView):

  def inaccessible_callback(self, name, **kwargs):
     if current_user.is_authenticated:
        abort(403)
     else:
        return redirect(url_for('security.login', next=request.url))

  @property
  def _form_edit_rules(self):
      return rules.RuleSet(self, self.form_rules)

  @_form_edit_rules.setter
  def _form_edit_rules(self, value):
      pass

  @property
  def _form_create_rules(self):
      return rules.RuleSet(self, self.form_rules)

  @_form_create_rules.setter
  def _form_create_rules(self, value):
      pass

  @property
  def form_rules(self):
      form_rules = [
          rules.FieldSet(('team'), 'Personal Info'),
          rules.Header('Project Info'),
          rules.Field('project_name')
      ]
      if not has_app_context() or current_user.has_role('superuser'):
          form_rules.append('approve')
      form_rules.append(rules.Container('rule_demo.wrap', 
          rules.Field('notes')))
      return form_rules

enter image description here

答案 3 :(得分:0)

我想合并 FileAdmin (例如:https://github.com/flask-admin/flask-admin/tree/master/examples/file)。

这意味着只有在项目获得批准后(见图),用户才能将文件上传到系统自动指定的路径(例如:/Reviewer1/Reviewer2/file

enter image description here