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

发布于 2024-12-14 21:21:26 字数 2348 浏览 1 评论 0原文

我希望能够在服务器端轻松创建由变色龙和金字塔支持的ajax“小部件”。

Pyramid 是否提供任何可以使编写小部件变得容易的管道代码?

我当前的方法是我有一个使用 home.pt 作为渲染器的主视图。 home.pt 使用宏 base.pt 定义页面结构并为 home.pt 提供填充槽。 base.pt 还使用我编写的登录“widget”宏(请参阅下面的 account_login_widget.pt)。

从理论上讲,这一切听起来都很棒...我有一个可在许多页面中使用的可重用登录小部件,但我当前的方法效果不佳。我的登录小部件在其渲染器中使用 ${username} 等变量(服务器需要定义)。我希望登录小部件及其渲染尽可能独立。但按照我目前的做法,主视图代码需要了解登录小部件的需求,并在字典中提供用户名、formrender 和其他变量。绝对不好...

我觉得我已经接近正确的想法,但缺少一些东西...

有什么想法吗?

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:

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

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>

I would like to be able to easily create ajax 'widgets' backed by chameleon and pyramid on the server side.

Does Pyramid provide any plumbing code that would make writing widgets easy?

My current approach is I have a home view which uses home.pt as the renderer. home.pt uses a macro base.pt which defines the page structure and provides a slot for home.pt to fill. base.pt also uses a login 'widget' macro that I have written (see: account_login_widget.pt below).

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). 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. Definitely not good...

I feel like I'm close to the right idea, but missing some things...

Any thoughts?

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:

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

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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那些过往 2024-12-21 21:21:26

处理此问题的一个好方法是将您的 account_login_widget 与其自己的视图相关联,例如:

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

然后您应该能够访问 http://yourapp /login_widget 并仅返回小部件的 HTML。

剩下要做的就是调用视图并将生成的 HTML 包含在模板中。也就是说,

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

您需要的不是:

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

render_view 但模板中不存在;您必须自己提供。为此,最好使用渲染前事件: 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

完成。如果您需要通过 AJAX 动态(重新)加载小部件,此方法也会有所帮助。

A good way of dealing with this is to associate your account_login_widget with its own view, like:

@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.

What's left to do is to call the view and include the resulting HTML in your template. 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; 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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文