Django: extend overridden template - python

I have two applications in my settings.INSTALLED_APPS:
INSTALLED_APPS = [
'application2',
'application1'
]
and want application2 to change a template from application1 (e.g. by adding a button).
How can achieve this without overriding the whole template?
NOTE
The problem is that the two templates have the same name ("mytemplate.html") and the same folder name ("application1"):
\project_root
\application1\templates\application1\mytemplate.html
\application2\templates\application1\mytemplate.html
so that I cannot write:
{% extends "application1\mytemplate.html" %}
because both templates are named "application1\mytemplate.html".

I don't think this is possible for the case you describe because it implies that INSTALLED_APPS order matters. As it is stated in the django book:
The order of INSTALLED_APPS doesn’t matter, but we like to keep things alphabetical so it’s easy for a human to read.
I understand that this is not the official documentation. However the book is authored by Adrian Holovaty and Jacob Kaplan-Moss (the Django creators), so I'll take their word on it.
But if you think a bit about it you will see why ordering is not such a great idea:
It only helps in specific - easy cases. In slightly more complex cases it wouldn't help. E.g.:
You have app1, app2, app3.
Both app2 and app3 extend/override templates app1/a.html and app1/b.html.
You want to use a.html as defined in app2 and b.html as defined in app3.

I don't think it is possible, unless you have different template names, then you can use {{ block.super }}
Once loader finds correct file, it doesn't look any further, so you don't have an access to overridden template in your new template.
https://code.djangoproject.com/browser/django/trunk/django/template/loaders/app_directories.py#L57

Templates aren't really owned by applications. They can be grouped into application directories if you like, but are pretty much independent of them.
The way to override part of a template, whatever application provided it, is to inherit from it using {% extends 'template_name.html' %} and then define whatever blocks you need to override. Of course, this means that the parent template will need to have those blocks already defined - otherwise you'll need to override the smallest relevant block that is defined, and repeat some of the content around the bit you need to change.

Related

How do I find where a django template variable comes from in the python

Is there a good general way of finding the line of python code responsible for passing in variables to django templates? When newly picking up a large code base, and I see {{ x.y }} in the template, and nothing obviously related (by how things are named) to x in the {% load ... %}, what do I do? Where can I find this variable in the python so that I can change it or related code?
My current solutions tend to be tedious and overwhelming. It's a lot of searching, but I would like to be able to just know where to look.
Look at the URL of the page. Then go to urls.py and look at which view is linked to the URL. Then open views.py and search for the view which the URL linked to.
In that view, the variable 'x' should be there. If it's not, then check the template context processors and middlewares as karthikr suggested.

Resolving template block structure conflicts with third-party django apps

When incorporating a third-party django app, I typically want it to be integrated aesthetically with the rest of my django project. While this is typically a matter of overriding the apps 'base.html' (if that), we all structure our templates a little differently, so incompatibilities often arise. For instance, suppose an app defines {% block footer %} and and makes use of it for a variety of things throughout its templates. If I am already using {% block footer %} for, say, a nav bar or copyright info, I don't want the app's templates to override my block.
A simpler, related case would be using different block names for the same thing. For instance, {% block extra-head %} versus {% block extrahead %}.
What's the best way of resolving these sorts of situations? Ideally, it would be nice to remap blocks, so you could do things like "put the child's {% block footer %} in the parent's {% block content-footer %}". Is there any way to get close to that? Or is the only solution to simply override every conflicting template?
First, the html inheritance should go:
my-sitebase.html
|-- app-base.html
|-- app-foo-template.html
I think this is what you meant, but the wording was a bit ambiguous. You might be able to just edit the app-base.html.
Second, a reusable app that overrides something like {% block footer %} is almost willfully causing trouble for anyone who uses it -- you should flag that in the provider's issue tracker.
If the app does do anything with {% block footer %} that should be done in the app-base.html area so you only have to change it once when integrating it with your site.
Finally, a recursive find-replace is actually very little effort. If you don't use an IDE that allows this, Text-Crawler is free, lightning fast, and a good non-IDE solution.
There have been a couple of attempts to create a standard inheritance pattern, I put together one that I like for the templates at djangoslingshot.com and I've seen one other -- but so far there hasn't been any coalescence around a standard. Likely because find-replace is actually a very low cost for the benefit of being able to do exactly what you want without someone else's rules getting in your way.

django template includes

I'm having an issue with django templates at the moment. I have 3 template files basically:
Base
story_list
story_detail
Story_list and _detail extend Base, and that works perfectly fine. However, list and detail share some code that extend the base template for my sidebar. I'm basically repeating a chunk of code in both templates, and the programmer in me says that's just wrong. There has to be a better way, I'm sure of it. I've tried includes, however I have in the included file:
{% block item %}
content stuff
{% endblock %}
for about 3 blocks. The problem is that none of that is being picked up/rendered. If I include the file in a block section that extends base, then it dumps everything properly, but if I don't include it in a block, I get nothing. Is SSI the way to go? I toyed with that, but that didn't seem to work properly either. Any help is appreciated.
Generally, using includes is not the answer with Django templates. Let me answer your question on several fronts.
First, let me address the sidebar.
Are nearly all the common pages going to be using that sidebar? Put it in Base. Don't override those sidebar blocks (i.e. don't write them at all in your Story_* templates).
Is this sidebar unique to the Story_* templates? Make another template called, say, Story_base and extend that. This is akin to making an abstract superclass in Java. (Answer was in my head, but wording was mercilessly ripped off from jpwatts.)
Next, let me address template inheritance. Say you have a template named Story_list that extends Base. At this point, after just putting {% extends "Base" %}, Story_list is exactly Base. Anything else you put in Story_list is ignored, because the template is already complete. The only thing you can do now is override blocks that have been defined in Base.
Finally, let me address includes. Try to always avoid them. Other templating engines, such as PHP, seem to encourage using includes. However, this can lead to less manageable templates in the long run. It's slightly harder to glance at an included snippet and immediately ascertain its place in your template hierarchy. They're also harder to refactor into the template hierarchy, especially if you include them at several levels (once in Base, twice in Story_base, once in some of the Story_*, etc.).
If there is common code between the story templates that isn't needed site-wide, I'd create a story_base (extending the original base) and have my story templates extend that.
You have an {% include %} tag for this.
{% include xxx.html %}
This tag works.
An alternative way is to use filter. Filter calls a function for rendering, template can be used while rendering.

Using Django admin look and feel in my own application

I like the very simple but still really elegant look and feel of the django admin and I was wondering if there is a way to apply it to my own application.
(I think that I've read something like that somewhere, but now I cannot find the page again.)
(edited: what I am looking for is a way to do it automatically by extending templates, importing modules, or something similar, not just copy&paste the css and javascript code)
Are you sure you want to take every bit of admin-site's look & feel??
I think you would need to customize some, as in header footer etc.
To do that, just copy base.html from
"djangosrc/contrib/admin/templates/admin/"
and keep it in
"your_template_dir/admin/base.html" or
"your_template_dir/admin/mybase.html"
Just change whatever HTML you want to customize and keep rest as it is (like CSS and Javascript) and keep on extending this template in other templates of your application. Your view should provide what it needs to render (take a look at any django view from source) and you'll have everything what admin look & feel had. More you can do by extending base_site.html in same manner.
(Note: if you keep the name
'base.html' the changes made in
html will affect Django Admin too.
As this is the way we change how
Django Admin look itself.)
{% extends "admin/base_site.html" %}
is usually a good place to start but do look at the templates in contrib/admin/templates and copy some of the techniques there.

Django.contrib.flatpages without models

I have some flatpages with empty content field and their content inside the template (given with template_name field).
Why I am using django.contrib.flatpages
It allows me to serve (mostly) static pages with minimal URL configuration.
I don't have to write views for each of them.
Why I don't need the model FlatPage
I leave the content empty and just supply a template path. Therefore I can take advantage of having the source in a file;
I can edit the source directly from the file system, without the help of a server (such as admin).
I can take advantage of syntax highlightning and other editor features.
With the model I have to maintain fixtures for flatpages.
So the data for the same entity is in two seperate places.
If I move the content inside the fixture it'll be more difficult to edit.
Even if fixture maintenance was a non-issue I'd still need to dump and load these fixtures again and again during development.
What I am looking for
Basically; getting rid of FlatPage model while maintaining contrib.flatpages functionality. I don't have a clear idea how this should be solved. If there's a clean way of modifying (like add_to_class) FlatPages to get the information somewhere other than the database I'd prefer that. Maybe the metadata can be inserted to the templates and then a special manager that reads this data would replace the default manager of FlatPages.
If I don't prefer manual editing over admin functionality for flatpages, how can take the database out of the equation?
Using the direct_to_template generic view would be a lot simpler. You could use the passed in parameters on one view to specify the actual template in urls.py, if you don't want to add an entry for each page:
r'^foo/(?P<template_name>.+)/$','direct_to_template', {'template': 'foo_index.html'}),
Then import the template in your foo_index.html:
{% include template_name %}

Categories