# 1: 从请求参数中获取URL 判断请求URL是安全的 返回请求的URl,如果没有获取到定位到首页。
return_url get_redirect_target() or self.get_url( .index_view )
# 2 判断我们定义的视图能否允许创建 如果不能创建 则返回首页。 可能是攻击方的伪造请求
if not self.can_create:
return redirect(return_url)
# 3: 从请求中拿到提交的form表单 然拷贝到这个form中来。
form self.create_form()
# 4:如果表单中没有校验属性 则
if not hasattr(form, _validated_ruleset ) or not form._validated_ruleset:
# 调用内置的表单属性校验 进行校验
self._validate_form_instance(ruleset self._form_create_rules, form form)
# 5 如果对表单校验成功
if self.validate_form(form):
# in versions 1.1.0 and before, this returns a boolean
# in later versions, this is the model itself
# 创建一个新的SQLAlchemy: model
model self.create_model(form)
# 创建成功
if model:
flash(gettext( Record was successfully created. ), success )
# 如果继续点击继续增加 重定向到增加地址
if _add_another in request.form:
return redirect(request.url)
# 如果继续点击的是编辑
elif _continue_editing in request.form:
# if we have a valid model, try to go to the edit view
# 如果model并不是True
if model is not True:
# 跳转到编辑页面
url self.get_url( .edit_view , id self.get_pk_value(model), url return_url)
else:
url return_url
return redirect(url)
else:
# 如果点击保存按钮 返回到保存页面
return redirect(self.get_save_return_url(model, is_created True))
# 得到表单中校验的数据。
form_opts FormOpts(widget_args self.form_widget_args,
form_rules self._form_create_rules)
# 如果允许创建 并参数中携带modal 则使用系统模板 则使用系统弹窗式的模板
if self.create_modal and request.args.get( modal ):
template self.create_modal_template
# 否则使用非弹窗式的模板
else:
template self.create_template
# 渲染模板JTML页面 并返回。
return self.render(template,
form form,
form_opts form_opts,
return_url return_url)
2 在ModelView中实现了create_model方法
def create_model(self, form):
try:
# 获取一个空的model
model self.model()
# 将form表单赋值给model对象
form.populate_obj(model)
# 数据加入到会话
self.session.add(model)
# 默认是啥也不做 如果需要在提交会话之前进行一些操作 可以修改这个函数。
self._on_model_change(form, model, True)
# 提交会话
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext( Failed to create record. %(error)s , error str(ex)), error )
log.exception( Failed to create record. )
self.session.rollback()
return False
else:
# 默认啥也不做 如果需要提交到数据库之后进行一些操作 则修改这个函数。
self.after_model_change(form, model, True)
return model
# 这个obj是model对象
def populate_obj(self, obj, name):
将form表单数据 赋值给model对象
values getattr(obj, name, None)
try:
ivalues iter(values)
except TypeError:
ivalues iter([])
candidates itertools.chain(ivalues, itertools.repeat(None))
_fake type(str( _fake ), (object, ), {})
output []
for field, data in zip(self.entries, candidates):
if not self.should_delete(field):
fake_obj _fake()
fake_obj.data data
field.populate_obj(fake_obj, data )
output.append(fake_obj.data)
setattr(obj, name, output)
1.2 修改操作
1 在baseModelView中定义了一个视图函数
expose( /edit/ , methods ( GET , POST ))
def edit_view(self):
return_url get_redirect_target() or self.get_url( .index_view )
if not self.can_edit:
return redirect(return_url)
# 获取该对象的ID
id get_mdict_item_or_list(request.args, id )
if id is None:
return redirect(return_url)
# 根据ID获取模板对象
model self.get_one(id)
if model is None:
flash(gettext( Record does not exist. ), error )
return redirect(return_url)
# 获取请求中新的表单 将值重新赋值给model(里面自动判断了POST,PUT才执行)
form self.edit_form(obj model)
if not hasattr(form, _validated_ruleset ) or not form._validated_ruleset:
self._validate_form_instance(ruleset self._form_edit_rules, form form)
if self.validate_form(form):
# 更新模板
if self.update_model(form, model):
flash(gettext( Record was successfully saved. ), success )
if _add_another in request.form:
return redirect(self.get_url( .create_view , url return_url))
elif _continue_editing in request.form:
return redirect(request.url)
else:
# save button
return redirect(self.get_save_return_url(model, is_created False))
# 如果是get 则可以预先填写一些信息
if request.method GET :
self.on_form_prefill(form, id)
form_opts FormOpts(widget_args self.form_widget_args,
form_rules self._form_edit_rules)
if self.edit_modal and request.args.get( modal ):
template self.edit_modal_template
else:
template self.edit_template
return self.render(template,
model model,
form form,
form_opts form_opts,
return_url return_url)
ModelView中的数据
def update_model(self, form, model):
try:
# form表单数据赋值给model
form.populate_obj(model)
# 修改之前的预先操作
self._on_model_change(form, model, False)
# 提交会话
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext( Failed to update record. %(error)s , error str(ex)), error )
log.exception( Failed to update record. )
self.session.rollback()
return False
else:
#修改后的处理操作 默认是None
self.after_model_change(form, model, False)
return True
1.3 查看详情操作
在baseModelView中定义了一个视图函数
这个只会存在get请求
expose( /details/ )
def details_view(self):
return_url get_redirect_target() or self.get_url( .index_view )
if not self.can_view_details:
return redirect(return_url)
id get_mdict_item_or_list(request.args, id )
if id is None:
return redirect(return_url)
# 根据id,获取model
model self.get_one(id)
if model is None:
flash(gettext( Record does not exist. ), error )
return redirect(return_url)
if self.details_modal and request.args.get( modal ):
template self.details_modal_template
else:
template self.details_template
template,模板
model model数据库数据
details_columns, 能够展示的列
get_value 根据能够展示的列 获取到的值
return_url 返回的URL
return self.render(template,
model model,
details_columns self._details_columns,
get_value self.get_list_value,
return_url return_url)
1.4 删除操作
expose( /delete/ , methods ( POST ,))
def delete_view(self):
Delete model view. only POST method is allowed.
return_url get_redirect_target() or self.get_url( .index_view )
if not self.can_delete:
return redirect(return_url)
# 获取删除表单数据
form self.delete_form()
if self.validate_form(form):
# 从表单中获取ID
id form.id.data
# 根据ID拿到form
model self.get_one(id)
if model is None:
flash(gettext( Record does not exist. ), error )
return redirect(return_url)
# 删除model
if self.delete_model(model):
flash(gettext( Record was successfully deleted. ), success )
return redirect(return_url)
else:
flash_errors(form, message Failed to delete record. %(error)s )
return redirect(return_url)
def delete_model(self, model):
try:
# 删除之前进行的操作 默认啥也不做
self.on_model_delete(model)
self.session.flush()
# 直接删除 并提交
self.session.delete(model)
self.session.commit()
except Exception as ex:
if not self.handle_view_exception(ex):
flash(gettext( Failed to delete record. %(error)s , error str(ex)), error )
log.exception( Failed to delete record. )
self.session.rollback()
return False
else:
self.after_model_delete(model)
return True
1.5 列出所有数据
expose( / )
def index_view(self):
if self.can_delete:
delete_form self.delete_form()
else:
delete_form None
# Grab parameters from URL
view_args self._get_list_extra_args()
# Map column index to column name
sort_column self._get_column_by_idx(view_args.sort)
if sort_column is not None:
sort_column sort_column[0]
# Get count and data
count, data self.get_list(view_args.page, sort_column, view_args.sort_desc,
view_args.search, view_args.filters)
list_forms {}
if self.column_editable_list:
for row in data:
list_forms[self.get_pk_value(row)] self.list_form(obj row)
# Calculate number of pages
if count is not None and self.page_size:
num_pages int(ceil(count / float(self.page_size)))
elif not self.page_size:
num_pages 0 # hide pager for unlimited page_size
else:
num_pages None # use simple pager
# Various URL generation helpers
def pager_url(p):
# Do not add page number if it is first page
if p 0:
p None
return self._get_list_url(view_args.clone(page p))
def sort_url(column, invert False):
desc None
if invert and not view_args.sort_desc:
desc 1
return self._get_list_url(view_args.clone(sort column, sort_desc desc))
# Actions
actions, actions_confirmation self.get_actions_list()
clear_search_url self._get_list_url(view_args.clone(page 0,
sort view_args.sort,
sort_desc view_args.sort_desc,
search None,
filters None))
return self.render(
self.list_template,
data data,
list_forms list_forms,
delete_form delete_form,
# List
list_columns self._list_columns,
sortable_columns self._sortable_columns,
editable_columns self.column_editable_list,
list_row_actions self.get_list_row_actions(),
# Pagination
count count,
pager_url pager_url,
num_pages num_pages,
page view_args.page,
page_size self.page_size,
# Sorting
sort_column view_args.sort,
sort_desc view_args.sort_desc,
sort_url sort_url,
# Search
search_supported self._search_supported,
clear_search_url clear_search_url,
search view_args.search,
# Filters
filters self._filters,
filter_groups self._get_filter_groups(),
active_filters view_args.filters,
# Actions
actions actions,
actions_confirmation actions_/confirm/iation,
# Misc
enumerate enumerate,
get_pk_value self.get_pk_value,
get_value self.get_list_value,
return_url self._get_list_url(view_args),