从“项目”抽象Django应用程序

时间:2010-09-05 12:52:55

标签: python django django-templates django-views

我正在努力弄清楚如何最好地做我认为我想做的事情 - 现在可能是我没有正确理解什么是最佳做法,所以如果没有,请随意嚎叫我等

基本上,我的问题是,如何正确地抽象应用程序功能,所述功能是在作为项目一部分的应用程序中找到的?

为此提供一些背景(这与我想要实现的目标相差不远):

假设,我正在建立一个网站。我的网站有外观和感觉,我在一个没有模型的django应用程序中定义了base.html样板和各种css项目。

现在,我还在写一个django博客应用程序。我知道如何包含它以便模型出现在我当前的应用程序中,我非常高兴我能从各种包中使用我喜欢的任何方法并操纵模型并用它来做所有python。

我不明白的是如何处理意见。将模型存储在别处但是必须在我当前的项目中构建用户界面(并暗示任何后续项目)似乎是违反直觉的。所以,我想,很好,在我的项目中的app文件夹中包含urls,完成。

然后我当然要写意见,这很好。我能做到。

我无法理解的是模板是如何适应的:在我的应用中,我想提供这样的模板:

<div class="entry">
<a href=""><h2>{{ entry.Title }}</h2></a>
<p>Published on: {{ entry.date_published|date:"j F Y" }}</p>
{{ entry.body_html }}
</div>
<a href="">X comments.</a>&nbsp;<a href=""">Add Comment</a>&nbsp;<a href="">Link</a>

<div id="commentdiv">
{% if comments %}
    <ul id="commentlist">
    {% for comment in Comments %}
        <li></li>
    {% endfor %}
    </ul>
{% else %}
    <p>There are no comments on this entry.</p>
{% endif %}

</div>

用于查看条目,因此在我的网站上,我转到sitename.com/blog/...someparameters.../entryname' where blog is the包含相关根项目的in urls.py`。一切都很好,但我如何附加该项目的样板,即外观和感觉?我可以全力以赴为博客应用程序设计一个基本模板,公平,但导航等呢?我可能希望在每个页面上都包含相同的标题,即使内容相当多样化。

现在,我知道{%extends“模板”%}指令和{%include template%}指令。为什么这些根据我的理解不起作用:

  • {%extends%} - 我如何知道/提供我想从根项目扩展的内容?如果你能为此提供一种机制,我认为它可以很好地解决问题。
  • {%include%} - 暗示我必须在根项目的bootstrap应用程序中为博客提供视图。我真的不想这样做 - 如果是这样的话,我不妨将整个项目移到那里。

所以我的问题是,如何把它们放在一起?

修改:我认为this question与我提出的问题非常相似,并注意到了答案。但是,他们仍然不满足。

3 个答案:

答案 0 :(得分:1)

如果我理解你的问题,那么我建议你做Custom Template Tag。在其中,您可以执行任何操作:对标记使用0或更多args来获取和操作任意对象,然后“手动”调用模板引擎以获取返回的代码段。 E.g。

[...]
t = loader.get_template('sometemplate.html')
c = Context({
    'my_data': my_data, # or whatever
})
return t.render(c) # this gets inserted into the invoking template

如果你不想让网站的各个“主要模板”执行{%load ...%},那么你可以在app目录的__init__.py中添加如下内容:

from django import template
template.add_to_builtins('myapp.templatetags.myapptags')

这使得它可以在网站的任何地方使用,就像任何其他内置的一样。

答案 1 :(得分:0)

如果您希望以有意义的方式使用template inheritance和django,则不仅需要使用{% extends %}标记,还需要使用{% block %}标记!在基本模板中指定应用需要替换的块:例如:

<html>
    <body>
         <div id="content">
         {% block "content" %}
         {% endblock %}
         </div>
    </body>
</html>

然后,您可以使用模板继承轻松填充div的内容:

{% extends "base.html" %}
{% block "content" %}
    The content generated by your app.
{% endblock %}

你应该记住,Django的模板语言也试图实现不重复自己的概念,所以尽量避免使用继承/包含重复块,它会给你一个更好维护的项目!

答案 2 :(得分:0)

执行此操作的典型方法是使用基本模板,在应用中对其进行扩展,并将您喜欢的任何块替换为应用内容,并使用模板标记从其他应用中引入内容。

例如:

base.html(在项目的模板中):

<html>
  <head>
    <title>{% block "title" %}Default title{% endblock %}</title>
  </head>
  <body>
    <div id="nav">{% block "nav" %}{% endblock %}</div>
    <div id="content">{% block "content" %}{% endblock %}</div>
  </body>
</html>

template_name.html(在应用的模板中):

{% extends "base.html" %}

{% load other_app_tags %}

{% block "nav" %}
  {% other_app_nav_tag %}
{% endblock %}

{% block "content" %}
  lotsa good junk.
{% endblock %}

other_app_tags.py(在另一个app的templatetags目录中):

from django import template

register = template.Library()

@register.inclusion_tag('navigation.html')
def other_app_nav_tag():
    # You could give this tag arguments to change how it behaves
    return {
        'links': {
            'Home': '/home'
        }
    }

navigation.html(在其他应用的模板中):

<ul>
{% for text, target in links %}
  <li><a href="{{ target }}">{{ text }}</a></li>
{% endfor %}
</ul>

这会使用inclusion tags从其他应用的模板中呈现。这是将模板包含到他们自己的相关应用程序中并且仍然可以在整个站点中使用的好方法。