在另一个页面中嵌入可选的 Django 应用程序(如果该应用程序存在)

发布于 2024-12-21 20:55:10 字数 518 浏览 2 评论 0原文

我们在多个站点安装了 Django 项目。其中一些还会有一个应用程序,它会生成一个状态框,该状态框应该显示在首页上。如果应用程序恰好安装了,那么让它显示的正确方法是什么。如果应用程序不存在,则不应显示任何内容。

我想我可以通过让状态应用程序扩展主索引页来做到这一点:

{% extends "mainproject/index.html" %}

{% block statusboxplaceholder %}
<div> status here </div>
{% endblock %}

这是正确的、惯用的方法吗?为了添加一点内容而扩展整个首页似乎有点违反直觉。

编辑:另外,我如何管理我的应用程序想要定义自己的“索引”页面,该页面应该优先于项目范围的“索引”页面显示?我显然不想在项目的 urls.py 中硬编码对它的引用。我是否创建一个特定于部署的 urls.py 来引用该部署中安装的特定应用程序?如果是这样,这不是重复 INSTALLED_APPS 中的信息,从而违反了 DRY 吗?

We have a Django project installed at multiple sites. At a couple of them, there will also be an app which produces a status box which should show on the front page, say. What's the right way to have it show up, if the app happens to be installed. If the app is not present, then nothing should display.

I think I could do it by having the status app extend the main index page:

{% extends "mainproject/index.html" %}

{% block statusboxplaceholder %}
<div> status here </div>
{% endblock %}

Is that the right, idiomatic approach? It seems slightly counterintuitive to extend the entire front page just to add a little bit of content.

EDIT: Also, how do I manage the fact that my app will want to define its own "index" page, that should be shown in preference to the project-wide "index" page? I obviously don't want to hard-code a reference to it in the project's urls.py. Do I create a deployment-specific urls.py which refers to specific apps that are installed at that deployment? And if so, isn't that repeating the information in INSTALLED_APPS, and hence violating DRY?

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

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

发布评论

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

评论(1

还给你自由 2024-12-28 20:55:11

虽然我不认为您的方法有问题,但我认为通用模板标记将提供最大的灵活性,特别是如果您想将此功能扩展到稍后可能安装的其他应用程序。

您的基本模板加载通用“boxes”标签。在标签的源中,您可以根据该特定实例安装的应用程序呈现您想要的任何内容。因此,您可以拥有一组默认应用程序来渲染框,或者最终用户可以自定义哪些应用程序应该渲染框。

在您的设置、配置甚至标签本身中,您可以识别要为每个应用程序的块呈现的模板。

假设每个应用程序在 app/templates 目录中都有其模板 - 这个 psuedo 应该可以让你继续(这是未经测试的):

from django.conf import settings
from django import template
register = template.Library()

class GenericBox(template.Node):
   def __init__(self, app):
      self.app = app
   def render(self, context):
      if self.app not in settings.INSTALLED_APPS:
         return '' # if the app is not installed
      # Here you would probably do a lookup against
      # django.settings or some other lookup to find out which
      # template to load based on the app.
      t = template.loader.get_template('some_template.html') # (or load from var)
      c = template.RequestContext(context,{'var':'value'}) # optional
      return t.render(c)    

@register.tag(name='custom_box', takes_context=True, context_class=RequestContext)
def box(parser, token):
    parts = token.split_contents()
    if len(parts) != 2:
        parts[1] = 'default_app' # is the default app that will be rendered.
    return GenericBox(parts[1])

Although I don't see a problem with your approach, but I think a generic template tag would provide the most flexibilty, especially if you want to extend this ability to other applications that you might install later.

Your base template loads a generic "boxes" tag. In the tag's source, you can then render whatever you want based on the installed apps for that particular instance. So you can have a set of default apps to render boxes for, or the end user can customize which apps should have boxes rendered.

In your settings, configuration or even in the tag itself, you can identify the template to render for the block per app.

Assuming that each app has its templates in app/templates directory - this psuedo should get you going (this is untested):

from django.conf import settings
from django import template
register = template.Library()

class GenericBox(template.Node):
   def __init__(self, app):
      self.app = app
   def render(self, context):
      if self.app not in settings.INSTALLED_APPS:
         return '' # if the app is not installed
      # Here you would probably do a lookup against
      # django.settings or some other lookup to find out which
      # template to load based on the app.
      t = template.loader.get_template('some_template.html') # (or load from var)
      c = template.RequestContext(context,{'var':'value'}) # optional
      return t.render(c)    

@register.tag(name='custom_box', takes_context=True, context_class=RequestContext)
def box(parser, token):
    parts = token.split_contents()
    if len(parts) != 2:
        parts[1] = 'default_app' # is the default app that will be rendered.
    return GenericBox(parts[1])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文