简体   繁体   English

金字塔和变色龙中的ajax小部件

[英]ajax widgets in pyramid and chameleon

I would like to be able to easily create ajax 'widgets' backed by chameleon and pyramid on the server side. 我希望能够在服务器端轻松创建由变色龙和金字塔支持的ajax'小部件'。

Does Pyramid provide any plumbing code that would make writing widgets easy? Pyramid是否提供任何管道代码,使编写小部件变得容易?

My current approach is I have a home view which uses home.pt as the renderer. 我目前的方法是我有一个使用home.pt作为渲染器的主视图。 home.pt uses a macro base.pt which defines the page structure and provides a slot for home.pt to fill. home.pt使用宏base.pt定义页面结构,并为home.pt提供填充的插槽。 base.pt also uses a login 'widget' macro that I have written (see: account_login_widget.pt below). base.pt也使用我编写的登录“widget”宏(参见下面的account_login_widget.pt)。

In theory, this all sounds great...I have a reusable login widget that I can use in many pages, but my current approach doesn't work very well. 从理论上讲,这一切听起来都很棒......我有一个可以在许多页面中使用的可重用登录小部件,但我目前的方法效果不佳。 My login widget uses variables like ${username} in its renderer (which the server needs to define). 我的登录窗口小部件在其渲染器中使用了像$ {username}这样的变量(服务器需要定义)。 I want the login widget and its rendering to be as independent as possible. 我希望登录小部件及其渲染尽可能独立。 But with my current way of doing things, the home view code needs to be aware of the login widget's needs and provide username, formrender and other variables in the dictionary. 但是根据我目前的做事方式,主视图代码需要了解登录窗口小部件的需求,并在字典中提供用户名,formrender和其他变量。 Definitely not good... 绝对不好......

I feel like I'm close to the right idea, but missing some things... 我觉得我接近正确的想法,但遗漏了一些东西......

Any thoughts? 有什么想法吗?

base.pt: base.pt:

<html>
<head></head>
<body>
<div id="container">
    <div id="header">
        <span metal:use-macro="load: account_login_widget.pt"></span>     
    </div>
    <div id="middle">
        <span metal:define-slot="content"></span>
    </div>
    <div id="footer"></div>
</div>
</body>
</html>

home.pt: home.pt:

<div metal:use-macro="load: base.pt">
<span metal:fill-slot="content">
    <div>my stuff</div>
</span>
</div>

account_login_widget.pt: account_login_widget.pt:

<span metal:define-macro="account_login_widget">
<script type="text/javascript">
(function($) {
    $.fn.my_function = function() {
        $('#login_form').submit(function(e) {
            e.preventDefault();

            // ajax call
            $.post(some_url, some_data, function(response) {
                $('#account_login_widget').html(response);
            });
        };
        return this;
    };
})(jQuery);

// Define the entry point    
$(document).ready(function() {
    $(document).my_function();
});
</script>

<div id="account_login_widget">
<div id="login_bar" tal:condition="not username">
    ${form_renderer.begin(...)}
        ... my form ...
    ${form_renderer.end()}
    <span tal:condition="login_failed">Login failed</span>
    <div id="forgot_password_link"><a href="#">Forgot Password?</a></div>
    <div id="create_account_link"><a href="${signup_url}">Create Account</a></div>
</div>
<div tal:condition="username">
    Welcome <strong>${username}</strong>! <a href="${logout_url}">Logout</a>
</div>
</div>
</span>

A good way of dealing with this is to associate your account_login_widget with its own view, like: 处理此问题的一个好方法是将account_login_widget与其自己的视图相关联,例如:

@view_config(name='login_widget',
             renderer='templates/account_login_widget.pt')
def login_widget(request):
    return {'username': ...}

You should then be able to visit http://yourapp/login_widget and get back only the widget's HTML. 然后,您应该能够访问http:// yourapp / login_widget并仅返回小部件的HTML。

What's left to do is to call the view and include the resulting HTML in your template. 剩下要做的就是调用视图并在模板中包含生成的HTML。 That is, instead of: 也就是说,而不是:

<span metal:use-macro="load: account_login_widget.pt"></span>

you'll want something like: 你会想要这样的东西:

<span tal:replace="structure render_view('login_widget')"></span>

render_view however doesn't exist in templates; 但是,模板中不存在render_view ; you'll have to provide it yourself. 你必须自己提供。 It's best to use the Before Render Event for this: http://docs.pylonsproject.org/projects/pyramid/dev/narr/hooks.html#beforerender-event 最好使用Before Render事件: http//docs.pylonsproject.org/projects/pyramid/dev/narr/hooks.html#beforerender-event

from pyramid.events import subscriber
from pyramid.events import BeforeRender
from pyramid.view import render_view_to_response

@subscriber(BeforeRender)
def add_render_view_global(event):
    event['render_view'] = lambda name: render_view_to_response(context, request, name, secure).ubody

Done. 完成。 This approach will also help should you ever need to (re)load widgets dynamically through AJAX. 如果您需要(重新)通过AJAX动态加载小部件,这种方法也会有所帮助。

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

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