Abstract Django Application from "Project"
I'm struggling to work out how best to do what I think I want to do - now it may be I don't have a correct understanding of what's best practice, so if not, feel free to howl at me etc.
Basically, my question is, how do I abstract application functionality correctly, said functionality being found in an application that is part of a project?
To put some context on this (this is not far away from what I'm trying to achieve):
Suppose, I am building a website. My website has a look and feel and I've defined a base.html
piece of boilerplate and various css-items in a model-less django app.
Now, I'm also writing a django blog application. I know how to include it so that the models appear in my current application and I'm more than happy that I can use any method I like from the various packages and manipulate the models and do thing all python with it.
What I don't understand is how to deal with views. It seems counter-intuitive to have the models stored elsewhere but have to build the user interface in my current project (and by implication any subsequent project). So, I thought, fine, include urls
from my app folder in my project, done.
Then of course I have to write views, which is fine. I can do that.
What I can't get my head around is how templates fit in: in my app, I want to serve a template like this:
<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> <a href=""">Add Comment</a> <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>
for viewing an entry, so on my site I go to sitename.com/blog/...someparameters.../entryname' where blog is the
includein
urls.py` of the root project in question. All fine and well, but how do I also attach the boilerplate from that project i.e. the look and feel? I could go all out and design a base template for the blog application, fair enough, but what about navigation etc? I might want to include the same header on every page even if the content is fairly diverse.
Now, I'm aware of the {% extends "template" %} directive and {% include template %} directive. Why these don't work as far as I understand it:
- {% extends %} - how do I know/provide what I want to extend from the root project? If you can provide a mechanism for this I think it would solve the problem very well.
- {% include %} - implies I have to provide views for the blog in a bootstrap application in the root project. I really don't want to do this - I might as well move the entire project into that if that开发者_StackOverflow中文版's the case.
So my question is, how do I put it all together?
Edit: I think this question is quite similar to what I'm asking and have noted the answers. However, they're still don't satisfy.
If I understand your problem correctly, then I would suggest doing a Custom Template Tag. In it you can do anything you want: use 0 or more args to the tag to get at and manipulate arbitrary objects, and then invoke the template engine "by hand" to get a snippet to return. 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
If you don't want to have the various "main templates" of the site do a {% load ... %} then you can stick something like the following in the __init__.py of the app directory:
from django import template
template.add_to_builtins('myapp.templatetags.myapptags')
Which makes it available anywhere in the site, just like any other built-in.
If you want to use template inheritance with django in a way that makes sense, you do not only need to use the {% extends %}
tag but also the {% block %}
tag! Specify in your base template the blocks that your app needs to replace: E.g.:
<html>
<body>
<div id="content">
{% block "content" %}
{% endblock %}
</div>
</body>
</html>
You can then easily fill the content of the div with your app with template inheritance:
{% extends "base.html" %}
{% block "content" %}
The content generated by your app.
{% endblock %}
You should keep in mind that also Django's template language tries to fulfill the concept of not repeating yourself, so try to avoid repeating block's with inheritance / inclusion, it will give you a project that is much nicer to maintain!
The typical way to do this is to use a base template, extend it in your app and replace any blocks you like with your app's content, and use template tags to bring in content from other apps.
For example:
base.html (in your project's templates):
<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 (in the app's templates):
{% extends "base.html" %}
{% load other_app_tags %}
{% block "nav" %}
{% other_app_nav_tag %}
{% endblock %}
{% block "content" %}
lotsa good junk.
{% endblock %}
other_app_tags.py (in the other app's templatetags dir):
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 (in the other app's templates):
<ul>
{% for text, target in links %}
<li><a href="{{ target }}">{{ text }}</a></li>
{% endfor %}
</ul>
This uses inclusion tags to render from your other app's templates. It's a good way to contain templates to their own relevant apps and still make them available throughout the site.
精彩评论