代码之家  ›  专栏  ›  技术社区  ›  Ludwik Trammer

在settins.py中注册的Django应用程序的自动发现小部件

  •  4
  • Ludwik Trammer  · 技术社区  · 16 年前

    标题可能有点混乱,但我不知道怎么称呼它。

    我想创建一个Django项目,其中包含一组可以任意打开或关闭的应用程序 INSTALLED_APPS syncdb ). 打开后,应用程序应能够自动:

    1. 在站点范围的搜索中注册它的内容。幸运的是 django-haystack 有这个内置的,所以这不是问题。

    2. 注册cron作业。 django-cron 确实如此。没问题。

    3. 注册一个应该显示在主页上的小部件。主页应该包括一个盒子列表,里面有来自不同应用程序的小部件。

      inclusion tags ,因为您可以将它们放在页面上的任何位置,它们可以控制内容和表示。问题是我不知道如何自动获取我的应用程序提供的包含标签列表,并在主页上逐个显示它们。我需要一种方法来注册它们,然后显示所有注册的标签。

    4 回复  |  直到 6 年前
        1
  •  5
  •   Clément    16 年前

    我不确定使用包含标签实际上是你最好的选择。。。AFAIK,没有简单的方法可以从模板动态调用模板标记(这不是模板标记的重点:-)。

    我想我可以对你的小部件做以下假设,如果我错了请纠正我:

    • 小部件呈现函数不需要来自模板上下文的参数
    • request 对象(以便它可以访问 user session 等…)

    这样,您就可以将小部件看作迷你视图,返回字符串而不是响应:

    def my_widget(request):
        ...
        # Here too, the function control both presentation and content
        return render_to_string('my_widget.html', {'foo': bar})
    

    现在有两个问题需要解决:

    1. 如何有一个所有控件功能的动态列表 安装 应用程序,在模板中可用?
    2. 如何在模板中调用这些小部件函数?

    第一点

    一个简单的方法是依靠一个惯例。有一个统一命名的函数列表 template_widgets.py 所有应用程序中的模块,例如:

    ## myapp/template_widgets.py
    
    def shopping_cart(request):
        # do something with the session/user
        ...
        return render_to_string('myapp/widgets/cart.html', {'cart': cart})
    
    # Another widget func, not defined here
    from myapp.views import another_widget_func
    
    # The list of widget functions declared by this app
    widgets = (shopping_cart, another_widget_func,)
    

    INSTALLED_APPS ,并使其在所有模板中自动可用(使用 context processor ). 当然,最好是懒洋洋地加载这个列表,以确保如果您不打算使用它,就不要在构建它时浪费CPU周期。

    ## myproject/context_processors.py
    from django.utils.importlib import import_module
    from django.utils.functional import lazy
    
    def widgets(request):
        def get_all_widgets(request):
            from django.conf import settings
            widgets_list = []
            for app in settings.INSTALLED_APPS:
                try:
                    mod = import_module(app+'.template_widgets')
                    widgets_list.extend(mod.widgets)
                except ImportError:
                    pass
                except AttributeError:
                    # Couldn't find a widgets variable in app.template_widgets module,
                    # probably better to raise a custom exception
                    raise
            return widgets_list
        return {'widgets': lazy(get_all_widgets, list)(request)}
    

    第二点 :

    ## home.html
    ...
    <div id="widgets">
        {% for widget in widgets %}
            <div class="widget">
                {{ widget }}
            </div>
        {% endfor %}
    </div>
    

    但这行不通, {[widget}} 这里有电话吗,需要 请求

    ## myproject/context_processors.py
    ...
            # replace `return widgets_list` with the following
            return map(lambda w: lazy(w, str)(request), widgets_list)
    ...
    

    瞧,上面的模板代码现在应该可以工作了。

    笔记 :

        2
  •  0
  •   Pierre-Jean Coudert    16 年前

    你知道吗 Django-block

        3
  •  0
  •   Dmitry Shevchenko    16 年前

    __init__.py 您可以使用以下行创建文件:

    from django.template import add_to_builtins
    add_to_builtins('python.path.to.mytags')
    

    这样,当导入app模块时,标签库就会被加载到“内置”中,即在没有{%load%}的情况下随处可见的标签

        4
  •  0
  •   Almad    16 年前

    我会编写一个模板标记,它将在一个变量中填充包含标记的列表。询问 django.template.Library

    推荐文章