如何在Pylons中制作“AJAX模板”?

2 投票
3 回答
1051 浏览
提问于 2025-04-16 02:10

最近我在学习Pylons,想知道怎么能简单地把AJAX功能加到我的网站上。

比如说,我有一个登录表单,通常是通过 site.com/user/login 这个地址来访问的。一般来说,这个过程会用类似下面的代码来处理:

class UserController(BaseController):
   def login(self):
      render('/login.html')

login.html 是一个模板,它继承了基础模板,里面有头部、底部和导航侧边栏。就是一个简单的网页。

那么,我该怎么把这个变成AJAX呢?我需要创建两个login.html模板,对吧?处理控制器的login()方法有什么好的办法吗?我是不是应该设置一个GET变量,比如 &ajax=true,然后在调用render()的时候检查这个变量?

我想要一种干净利落的方法来选择我的控制器如何渲染内容,而不是用一些丑陋的黑科技(像上面提到的GET方法)。

大家有什么想法?

3 个回答

1

Mako的作者自己写了一篇博客文章,你可能会觉得很有意思。
文章的主要内容是一个用来渲染模板中单个“def”的函数:

def render_def(template_name, name, **kwargs):
    from pylons.templating import pylons_globals
    globs = pylons_globals()

    if kwargs:
        globs = globs.copy()
        globs.update(kwargs)

    template = globs['app_globals'].mako_lookup.get_template(template_name).get_def(name)
    return template.render(**globs)
2

我不太明白你的AJAX代码为什么会想要对那个login页面做一个GET请求——因为GET请求只是用来获取信息的,而客户端的JavaScript代码从登录表单中想要获取什么信息呢?

不过,假设确实有一些页面你希望AJAX代码能够通过GET请求来获取有用的信息,我建议使用像?format=json这样的查询字符串,这样可以明确请求“只要有用的JSON格式的信息,不需要其他装饰”。

这种方法不仅让你的应用知道这是一个自动化的请求(不管是AJAX还是其他方式,反正就是需要发送任何装饰,只要有用的信息就行!),而且特别说明了请求的格式是JSON(所以,如果将来你想提供XML或者其他格式作为替代,也有明显的扩展路径——比如?format=xml之类的)。

这并没有什么特别针对Python或者Pylons的内容——这是我推荐给任何“混合”网站的方法(至少在某些页面能够以多种格式响应,比如客户可以选择带装饰的HTML或JSON)无论它打算使用什么服务器端语言。

不过,如果你的渲染总是像somefunction(sometemplate, somecontext)这样的形式,你可以稍微调整一下,确保somefunction也能获取到请求的格式信息——如果请求的格式是JSON(或者,谁知道,将来可能是XML或其他格式),那么somefunction就知道可以忽略模板(毕竟模板应该是纯粹的视图相关功能,因此只应该包含展示内容),直接渲染上下文中的信息为JSON或其他格式。

3

现在的所有现代JavaScript库在它们的AJAX请求中都会设置一个叫“X-Requested-With: XMLHttpRequest”的头信息。为了方便,Pylons会检查这个头信息,如果找到了,就会把一个叫 request.is_xhr 的布尔值设置为真或假。

在Mako中,条件继承有点复杂,因为 <%inherit> 的处理方式。不过,下面是你该怎么做:

  1. 在你的控制器中,把render()的调用改成 render('/login.html', {'ajax': request.is_xhr})

  2. 在你的模板中,把你不想放在AJAX模板里的内容分开,使用 模板继承

  3. 使用类似这样的 <%inherit>: <%inherit file="${None if context.get('ajax') else 'login_base.html'}"/>

(注意:render()的语法没有什么特别的。你也可以直接使用 c.ajax = request.is_xhrcontext.get('c').ajax)

撰写回答