To add some content to a Django admin view of a model, I want to override the change_form.html template. According to the documentation I would need to create a file change_form.html in a the folder /project-path/templates/admin/appname/modelname/. Of course I need to make sure, that this path is also available in TEMPLATE_DIRS. Such a file could look like this:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block after_field_sets %}
SOME CONTENT
{% endblock %}
However, I make use of django-guardian to have object permissions. This Django app overrides change_form.html as well (which works fine -- relevant source seems to be here), but Django doesn't pick up my template extension file (i.e. "SOME CONTENT" from the sample above isn't displayed). The blocks/parts I want to override are not the same ones that django-guardian overrides and eventually I want to have the additions to change_form.html of django-guardion and of my template.
What am I doing wrong here? And is possible at all to have multiple applications overriding an admin template?
If it is of interest, this is my TEMPLATE_LOADERS setting:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader'
)
Also, django-guardian is the last app in the INSTALLED_APPS array.
One possible solution seems to be to explicitly define the inheritance chain by referring to and overriding django-guardian's template (defined here) and not Django's general change_form.html. So instead of using
{% extends "admin/change_form.html" %}
in the beginning of my custom template, I would need to use
{% extends "admin/guardian/model/change_form.html" %}
Also I would need to extend my GuardedModelAdmin sub-class model to explicitly use my own template file as the change form template:
class MyModel(GuardedModelAdmin):
change_form_template = 'admin/appname/mymodel/change_form.html'
This works, but it adds a clear dependency to the template and the model. Of course, the model has this dependency anyway, but I would be interested if there is also a solution that refers only to the default change_form.html -- however, I suspect that this is not really possible.
If a path to your template is in TEMPLATE_DIRS, then you can reverse order of your TEMPLATE_LOADERS.
If your template in in your app, then you need to add your app after django-guardian in INSTALLED_APPS array.
Basically, if there are name collisions, then last loaded template will be in use.
Related
I have a main template main.html from which I extend from, I want to load the i18m library on it or globally to evade using {% load i18n %} everywhere.
How i could do that?
This is unfortunately not possible. See the docs :
When you load a custom tag or filter library, the tags/filters are
only made available to the current template – not any parent or child
templates along the template-inheritance path.
For example, if a template foo.html has {% load humanize %}, a child
template (e.g., one that has {% extends "foo.html" %}) will not have
access to the humanize template tags and filters. The child template
is responsible for its own {% load humanize %}.
This is a feature for the sake of maintainability and sanity.
I have some flatpages and I need to display it's content in a separate view.
What I am doing right now is to get those flatpages by url in the actual view using something like:
{% load flatpages %}
{% get_flatpages '/about/' as about_pages %}
Following the documentation I found in https://docs.djangoproject.com/en/1.9/ref/contrib/flatpages/
I would like to get those flatpages in my views.py and pass them as variables to whatever view I want.
Any idea about how to accomplish this?
Flatpages are just models, like anything else; you can query them and pass the instances around however you like.
from django.contrib.flatpages.models import FlatPage
flatpage = FlatPage.objects.get(url='/about/)
I am new to django and I misunderstand how to use templates.
I have a a file called base.html which I see as a parent to hello.html.
In hello.html I have this syntax:
{% extends "base.html" %}
{% block hello %}
<h1>hello</h1>
I should see this template. This is the hello.html template.
{% endblock %}
In base.html I have this syntax:
{% block hello %}{% endblock %}
It is my understanding that django should render hello.html inside of base.html
When I deploy my two html files, django ignores my syntax.
Question: How to render hello.html in base.html?
The files are visible inside of github:
https://github.com/danbikle/sof1231/blob/master/hello/templates/base.html
https://github.com/danbikle/sof1231/blob/master/hello/templates/hello.html
Also I deployed them to heroku with these commands:
heroku create sof1231
git push heroku master
You can see base.html deployed to https://sof1231.herokuapp.com
Again,
How to render hello.html in base.html?
To render a template in another template, you use include:
base.html
{% include 'hello.html' %}
Your templates are designed to work with inheritance, and there is nothing wrong with the simplified templates that you show in your question (I didn't check those on github).
I think that your problem might be caused by your view rendering the base.html template, when it should instead be rendering the hello.html template. You should add your view code to your question so that this can be verified. Your view code should be something like this, which renders the child template hello.html:
def hello(request):
template_variables = {'a': 1, 'b': 2}
return render(request, 'hello.html', template_variables)
Another answer (which you have accepted) recommends using include. I don't think that include is the correct approach.
There is a difference between inheriting from a base template and simple inclusion of content from another file. One important benefit of template inheritance is that you can add common content (e.g. menu, side bars, footers, etc.) to a "base" template and then inherit from that base in child templates without duplicating the common content for each page. Another benefit is that the child templates can override content in the base templates, e.g. <title>. This allows you to markup areas of your layout in the base template (using block) and then override the content of the block with other content. This is not possible with a simple include.
I'm trying to figure out what is the best way to have mixes member and guest templates.
The main difference would be the menu of the page. In some languages i've worked with you can add prefixes to templates to get it to switch out the whole templates for the other version.
ex:
base.guest.html
base.member.html
In Django the only way i've seen any thing related to this is this code i found in the documents:
if request.user.is_authenticated():
# Do something for authenticated users.
else:
# Do something for anonymous users.
Is this the base way to do this in Django? or is there something else that i'm missing.
For most of my pages this would work out ok but wasn't sure if there was a better way to switch content based on authenticated state.
You don't extend in this case, instead you include. The base.html should authentication-agnostic.
{% if user.is_authenticated %}
{% include 'member.html' %}
{% else %}
{% include 'guest.html' %}
{% endif %}
If you want to, you can do have the if-statement also in your view, and pass the name of the template-to-be-included to the main template. For more info see https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
I have the following template in template/admin/change_form.html:
{% extends "admin/change_form.html" %}
{% block extrahead %}
{% include "dojango/base.html" %}
{% block dojango_content %}
{% endblock %}
{% endblock %}
However for some reason it throws a
TemplatesyntaxError: TemplateSyntaxError at /admin/cms/post/add/
Caught RuntimeError while rendering: maximum recursion depth exceeded while calling a Python object
I know it's late, but...
If extending - which is a far better option than duplicating - the key is to have it named anything except /admin/change_form.html.
(Although the OP referred to template/admin/change_form.html, this is simply because a path in his TEMPLATE_DIRS tuple ends in '/template' - mine generally end in '/templates' - but, these directories can be named anything and located anywhere.)
It will be used automatically on a per-app basis if named /admin/<MyAppName>/change_form.html
It will be used automatically on a per-model basis if named /admin/<MyAppName>/<MyModelName>/change_form.html
It can be named anything if specified explicitly in the ModelAdmin
class MyModelAdmin(admin.ModelAdmin):
change_form_template = 'subdir/my_change_form.html'
Finally, if insistent on naming it /admin/change_form.html, you can - provided that the extends tag contains the full path to your django installation instead of a relative one.
You are in admin/change_form.html and you extend admin/change_form.html. You cannot extend the same template which you are in.
You probably expected that if you override template from admin application, you can extend the one you override. But this is not how it works. When you override a template you cannot access it.
Solution to your problem is to copy original template and change things you don't like.
Also, you can point your AdminOptions class to another template using the change_form_template property.
Something like:
class MyOptions(AdminOptions):
change_form_template = 'myapp/my_change_form.html'
And myapp/my_change_form.html:
{% extends "admin/change_form.html" %}
I had the same problem. Solved by placing the overridden template under myapp/templates/admin/myapp instead of myapp/templates/admin.
The best way to do this that I have found is to use '..' to go up a couple of directories, then go back down into directories that should only be found in the Django code base.
As the Django templates are in something like "django/contrib/admin/templates/admin", I found that this worked me:
{% extends "../../admin/templates/admin/change_form.html" %}
If that still causes a clash with some other structure you have, you could go further:
{% extends "../../../contrib/admin/templates/admin/change_form.html" %}
or even:
{% extends "../../../../django/contrib/admin/templates/admin/change_form.html" %}
Although it is a little hacky, at least by doing the above you don't have to use some other technique that involves copying the django source or setting up a symlink.
With Django core it's impossible. But it is not impossible.
Copy and paste "the original template and change things you don't like" it's very ugly.
Don't make in the templates, whatever you don't make in python
This solution is to any template:
http://pypi.python.org/pypi/django-smart-extends