3.2. 控制器check的实现

3.2.1. MVC中的数据流
3.2.2. 页面模板布局
3.2.3. 模板语法示例
3.2.4. 控制器的index方法
3.2.5. 控制器的submit方法
  1. 路由:用户访问URL或提交表单,由 Pylons 负责将请求路由至控制器中的同名方法;

  2. 调用模组:控制器访问模组 svnauthz 的相关调用,调用结果返回给控制器;

  3. 调用视图:调用视图模板,并向其传递参数用于填充模板;

  4. 模板展现:最终填充后的模板发向浏览器,最终展现给用户;

3.2.1. MVC中的数据流

3.2.1.1. 控制器获取用户请求

无论用户使用POST或者GET方式传递请求,都可以用 request.params 获取。

d = request.params  # request.params 是包含用户传参的dict

if d.get('userinput') == 'manual':
    username = d.get('username')     # 从文本框获取用户手工输入的用户名
else:
    username = d.get('userselector') # 从下拉框选择的用户名
3.2.1.2. 控制器向视图模板传参
c.access_map_msg ="<pre>"
c.access_map_msg+="\n\n".join(self.authz.get_access_map_msgs(username, repos))
c.access_map_msg+="</pre>"
return render('/check/index.mako')
3.2.1.3. 视图模板用参数填充
<input type="submit" name="submit" value="提交">
${h.end_form()}
  
<hr>
${c.access_right_msg}
<pre>
  ${c.access_map_msg}
</pre>

3.2.2. 页面模板布局

Check页面的布局参见:图 5 “控制器check的MVC框架示意图”

各个部分的含义为:

  1. 用户选择/输入框:选择或输入用户对象名称,可以为组、别名或用户名;

  2. 版本库选择/输入框:当选定一个版本库后,会更新③部分的授权路径列表;

  3. 授权路径选择/输入框:列表内容和版本库(②)相关;

  4. 权限检查按钮

  5. 结果输出

[注意]

其中:③和⑤是动态内容,②和④会触发表单提交。

3.2.3. 模板语法示例

Pylons缺省使用mako格式的模板。mako文件相当于ASP,PHP,JSP, 不过是Python语言的。模板文件的主体依旧是HTML,可以在模板中用“<% %>” 语法嵌入Python代码。例如:

<%
userlist = [[u'请选择...', '...'],
            [u'所有用户(含匿名)', '*'],
            [u'注册用户', '$authenticated'],
            [u'匿名用户', '$anonymous'],]
for i in c.userlist:
    if i == '*' or i =='$authenticated' or i == '$anonymous':
        continue
    if i[0] == '@':
        userlist.append([u'团队:'+i[1:], i])
    elif i[0] == '&':
        userlist.append([u'别名:'+i[1:], i])
    else:
        userlist.append([i, i])

reposlist = [[u'请选择...', '...'], [u'所有版本库', '*'], [u'缺省', '/'],]
for i in c.reposlist:
    if i == '/':
        continue
    reposlist.append([i, i])

pathlist = [[u'所有路径...', '*'],]
for i in c.pathlist:
    pathlist.append([i, i])
%>

可以用“${expression}”将页面Python代码的或者Controller 传递的变量/表达式的值直接嵌入到模板中输出。例如:

<input type="radio" name="reposinput" value="select" 
       ${c.checked_reposinput_select}> 选择代码库
  <select name="reposselector" size="0" onFocus="select_repos(this.form)">
    ${h.options_for_select(reposlist, c.selected_repos)}
  </select>

3.2.4. 控制器的index方法

class CheckController(BaseController):
    
    def __init__(self):
        self.authz = SvnAuthz(cfg.authz_file)
        c.reposlist = map(lambda x:x.name, self.authz.reposlist)
        c.userlist = map(lambda x:x.uname, self.authz.grouplist)
        c.userlist.extend(map(lambda x:x.uname, self.authz.aliaslist))
        c.userlist.extend(map(lambda x:x.uname, self.authz.userlist))
        c.pathlist = []
    
    def index(self):
        return render('/check/index.mako')

3.2.5. 控制器的submit方法

class CheckController(BaseController):
    ...
    def submit(self):
        d=request.params
        # 从 request.params 中获取用户名、版本库名、路径等
        if d['reposinput'] == 'manual':
            repos = d['reposname']
        else:
            repos = d['reposselector']
        # 略去参数解析
        ...
        # 通过上下文对象传递Model返回值
        c.access_map_msg ="<pre>"
        c.access_map_msg+="\n\n".join(self.authz.get_access_map_msgs(username, repos))
        c.access_map_msg+="</pre>"
        # 调用并返回填充后的视图模板
        return render('/check/index.mako')