问题
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?
回答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])
来源:https://stackoverflow.com/questions/8557479/embed-an-optional-django-application-in-another-page-if-that-app-is-present