简体   繁体   English

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

[英]How can I make 'AJAX templates' in Pylons?

I've been getting into Pylons lately and was wondering how I could go about easily integrating AJAX functionality into my websites. 我最近进入Pylons,想知道如何才能轻松地将AJAX功能集成到我的网站中。

Basically, lets say I had a login form that usually gets accessed via site.com/user/login . 基本上,可以说我有一个登录表单,通常可以通过site.com/user/login访问。 Now, generally, this will be handled via something like: 现在,通常将通过以下方式处理:

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

login.html would be a template that inherits the base, has a header, footer and navigation sidebar. login.html是继承基础的模板,具有页眉,页脚和导航侧栏。 A plani, simple website. 一个简单的网站。

How could I AJAXify this? 我该如何AJAXify? I would need to create two login.html templates, right? 我将需要创建两个login.html模板,对吗? What would be a good way to handle the controller's login() method? 什么是处理控制器的login()方法的好方法? Should I set a GET variable of something like &ajax=true then check for that when issuing render()? 我是否应该设置类似&ajax=true的GET变量,然后在发出render()时检查该变量?

I want a nice and clean way to choose how my controllers render content instead of some ugly hack (like the GET method above). 我想要一种不错的方法来选择控制器呈现内容的方式,而不是一些难看的技巧(例如上面的GET方法)。

Thoughts? 思考?

All modern Javascript libraries set an "X-Requested-With: XMLHttpRequest" header in their AJAX wrappers. 所有现代Javascript库在其AJAX包装器中都设置了“ X-Requested-With:XMLHttpRequest”标头。 As a convenience, Pylons sets the request.is_xhr boolean if it finds this header. 为了方便起见,如果Pylons找到了此标头,则将其设置为request.is_xhr布尔值。

Conditional inheritance is a little tricky in Mako because of how <%inherit> is handled , but here's what you do: 由于<%inherit>是如何处理的 ,因此在Mako中,条件继承有点棘手,但是您可以执行以下操作:

  1. Change the render() call in your controller to render('/login.html', {'ajax': request.is_xhr}) 将控制器中的render()调用更改为render('/login.html', {'ajax': request.is_xhr})

  2. In your template, separate out anything you don't want in your AJAX template using template inheritance . 在模板中,使用模板继承将AJAX模板中不需要的所有内容分离出来。

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

(Note: There's nothing special about the render() syntax used. You could just as easily use c.ajax = request.is_xhr and context.get('c').ajax instead) (注意:所使用的render()语法没有什么特别的。您可以轻松地使用c.ajax = request.is_xhrcontext.get('c').ajax

I'm not sure why your AJAX code would want to do a GET on that login page -- GET is only for getting information, and what info would the JS code client-side want to obtain from a login form? 我不确定您的AJAX代码为什么在该login页面上执行GET - GET仅用于获取信息,JS客户端希望从登录表单中获取哪些信息?

Anyway, assuming there are pages that you want AJAX code to be able to GET in order to obtain useful info, I recommend a query string such as ?format=json to allow such requests to explicitly ask for "useful JSON-format info only, no decoration please". 无论如何,假设有一些页面您希望AJAX代码能够获取以便获得有用的信息,我建议使用查询字符串,例如?format=json以允许此类请求明确要求“仅有用的JSON格式的信息,请不要装饰”。

Not only does this approach allow your app to know that this is an automated request (AJAX or otherwise, who cares? point is, no cosmetics are to be sent in response, just useful info!) but specifically that the requested format is JSON (so, should you ever want to supply XML or whatever as an alternative, there's an obvious growth path -- ?format=xml and the like). 这种方法不仅使您的应用程序知道这是一个自动请求(AJAX还是其他,谁在乎?要点是, 没有化妆品会作为响应发送, 只是有用的信息!),而且特别是请求的格式为JSON(因此,如果您想提供XML或其他替代方法,则有一条明显的增长之路- ?format=xml等)。

There is nothing particularly Python-specific, much less Pylons-specific, in this -- it's the approach I would recommend for any "mixed" site (able, at least in some pages, to respond in more than one format, eg HTML with decorations or JSON, at clients' choice) no matter what sever-side language it was planning on using. 在这方面,没有什么特别的Python特有的东西,更不用说Pylons了,这是我建议任何“混合”站点使用的方法(至少在某些页面中,可以以多种格式响应,例如HTML和装饰或JSON(由客户选择),无论它计划使用哪种服务器端语言。

If your rendering is always of a form such as somefunction(sometemplate, somecontext) , though, you may tweak things to ensure that the somefunction also gets the crucial bit about requested format -- if the requested format is JSON (or, who knows, in the future maybe XML or whatever) then somefunction knows it can ignore the template (which after all is or should be a purely view related functionality, and therefore should have presentation contents only) and just proceed to render the info that's in the context as JSON or whatever. 但是,如果您的呈现始终是诸如somefunction(sometemplate, somecontext)之类的形式,则可以进行调整以确保somefunction也能获得关于请求格式的关键信息-如果请求的格式是JSON(或者,谁知道,将来可能是XML或其他任何东西),则somefunction知道它可以忽略模板(毕竟是或应该是纯视图相关的功能,因此应该仅具有演示内容),然后继续将上下文中的信息呈现为JSON等。

The author of Mako himself wrote a blog post that you might find interesting. Mako的作者本人写了一篇博客文章 ,您可能会觉得有趣。
The main point is a function to render a single "def" of a template: 要点是呈现模板的单个“ 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM