我已经构建了一个允许用户申请代码审查并等待经理批准的系统。
现在我想要实现的目标如下:
如果拒绝,
然后所有字段都变为可编辑。当然,在创建新项目时,所有字段都应该是可编辑的
课程Project
和ProjectView
的代码如下:
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib import sqla
from flask_security import current_user
# Create Flask application
app = Flask(__name__)
app.config.from_pyfile('config.py')
db = SQLAlchemy(app)
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
project_name = db.Column(db.Unicode(128))
version = db.Column(db.Unicode(128))
SVN = db.Column(db.UnicodeText)
approve = db.Column(db.Boolean())
def __unicode__(self):
return self.name
class ProjectView(sqla.ModelView):
def is_accessible(self):
if not current_user.is_active or not current_user.is_authenticated:
return False
return False
@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.Field('project_name'),
rules.Field('version'),
rules.Field('SVN'),
]
if not has_app_context() or current_user.has_role('superuser'):
form_rules.append('approve')
在我看来,由于批准是一个布尔变量,所以应该有一个 条件判断判断它是0还是1然后该字段变为只读或相应的可编辑。
感谢您提前提出建议。
答案 0 :(得分:3)
正如您已经注意到,为某个字段设置readonly
属性为rather simple但是将其设置为动态有点棘手。
首先,您需要一个自定义字段类:
from wtforms.fields import StringField
class ReadOnlyStringField(StringField):
@staticmethod
def readonly_condition():
# Dummy readonly condition
return False
def __call__(self, *args, **kwargs):
# Adding `readonly` property to `input` field
if self.readonly_condition():
kwargs.setdefault('readonly', True)
return super(ReadOnlyStringField, self).__call__(*args, **kwargs)
def populate_obj(self, obj, name):
# Preventing application from updating field value
# (user can modify web page and update the field)
if not self.readonly_condition():
super(ReadOnlyStringField, self).populate_obj(obj, name)
为您的观点设置form_overrides属性:
class ProjectView(sqla.ModelView):
form_overrides = {
'project_name': ReadOnlyStringField
}
您需要将自定义readonly_condition
函数传递给ReadOnlyStringField
实例。我找到的最简单的方法是覆盖edit_form方法:
class ProjectView(sqla.ModelView):
def edit_form(self, obj=None):
def readonly_condition():
if obj is None:
return False
return obj.approve
form = super(ProjectView, self).edit_form(obj)
form.project_name.readonly_condition = readonly_condition
return form
快乐的编码!
答案 1 :(得分:2)
对我而言,这个技巧是最简单的方法:
from flask_sqlalchemy import SQLAlchemy
from flask_admin.contrib.sqla import ModelView
from flask_admin.form.rules import Field
class Example(db.Model):
id = db.Column(db.Integer, primary_key=True)
not_editable = db.Column(db.Unicode(128))
editable = db.Column(db.Unicode(128))
class ReadonlyFiledRule(Field):
def __call__(self, form, form_opts=None, field_args={}):
field_args['readonly'] = True
return super(ReadonlyFiledRule, self).__call__(form, form_opts, field_args)
class ExampleView(ModelView):
form_edit_rules = (ReadonlyFiledRule('not_editable'), 'editable', )
更新(最简单的方法):
class ExampleView(ModelView):
form_widget_args = {
'not_editable': {
'readonly': True
}
}
答案 2 :(得分:1)
我在这里提出的上一个答案有一个重大缺陷。以下使用不同的方法,通过分析表单本身,并在满足特定条件时为特定表单添加readonly: True
到render_kw
。
class ProjectView(sqla.ModelView):
# ... other class code
def edit_form(self, obj=None):
# grab form from super
form = super(ProjectView, self).edit_form(obj)
# form.approved.data should be the same as approved
# if approved is included in the form
if form.approved.data:
if form.project_name.render_kw:
form.project_name.render_kw.update({
'readonly': True
})
else:
form.project_name.render_kw = {'readonly': True}
return form
这有点令人讨厌,它要求approved
处于编辑表单中。如果您使用此解决方案,则可以将approved
添加为readonly
字段,或者代替readonly
,您可以从上述类中的表单中删除approved
字段方法。