Difficulty overriding Django Admin template - django

I'm using Django 1.2.4 on Ubuntu 10.10. I'm trying to override the index.html template for the admin module. I've been following these instructions. I also looked at this question, but I'm still having difficulty.
The instructions say to create an admin directory in the templates directory:
templates/
admin/
index.html
I want to override a single block in the index.html. (Really, all I want to do is append some text to the end. Is there an easier way than copy/pasting the entire block and changing it?) (Update: Looks like {{block.super}} may help.)
To signal that I'm overriding, I put this at the top of my index.html:
{% extends "admin/index.html" %}
Of course, that results in a stack overflow (from the terminal):
Exception RuntimeError: 'maximum recursion depth exceeded in __subclasscheck__' in <type 'exceptions.RuntimeError'> ignored
What is the correct way to do this? I tried a symlink per an answer on the linked question, but that resulted in the following:
me#mycomp:~/foo$ sudo ln -s /usr/local/lib/python2.6/dist-packages/django/contrib/admin/templates/ django_admin
[sudo] password for me:
ln: creating symbolic link `django_admin': Protocol error
What am I doing wrong?

The recursion error is because you're extending the admin/index.html with itself.
You can either:
copy the entire admin/index.html template in your templates/admin/ directory, and it will replace the default template with yours
override the index.html per app or model, as explained here
I know this is late after the question, but you know, google traveling...

Amend settings.py with an extra template folder, for example:
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
"/home/mysite/webapps/django/myproject/templates",
"/home/mysite/webapps/django/lib/python2.7/django/", # extra folder
)
Then in myproject/templates/admin add your own index.html like:
{% extends "contrib/admin/templates/admin/index.html" %}
{% block branding %}
<h1 id="site-name">Administration for TheLittleButtonCo</h1>
{% endblock %}
Variations are possible, obviously. This works on Django 1.3.1 final

Not sure if you found the answer, but you need to change
{% extends "admin/index.html" %}
to
{% extends "admin/base_site.html" %}
as that is what the original index.html page overwrites. Because the Django system searches your templates folder before using the default admin one, so in this case it finds the admin/index.html in your templates, then it's trying to extend itself with the extend (hence the recursion error).
For reference you can customise the base_site.html in you templates too, it extends base.html. The best thing to do is copy the original from:
/usr/local/lib/python2.6/dist-packages/django/contrib/admin/templates/
and paste it into your templates folder as a starting point

I use an extra package, called django-smart-extends

Related

Django template nested include passing variables

I use django template index.html to render the frontpage. It includes another template to create a link icon. This template url_icon.html includes another template icon.html. When passing the arguments down the way, I face with an error. How to fix it?
index.html
.
.
.
{% include "url_icon.html" with name="return" url="/" %}
.
.
.
url_icon.html
{% include "icon.html" with icon={{ name }} %}
icon.html
<img src="/static/images/{{ name }}.png" />
Causing an error:
Could not parse the remainder: '{{' from '{{'
it looks like there are a few things you can do to improve/fix this. Addressing #1 and #2 should fix your issue. I've also added suggestions for best practices that would probably require refactoring (#3, #4).
It looks like you need to remove the curly-braces from name inside the {% include %} tag. Context variables can be used inside tags without extra syntax.
url_icon.html:
{% include "icon.html" with icon=name %}
icon.html will have access to name since you're not using the only keyword when updating its context, so your code might appear to work at first ({% include %} documentation). However, it looks like your intention is to refer to it as icon.
Use the variable icon in instead of name
icon.html:
<img src="/static/images/{{ icon }}.png" />
Optional suggestion: Use Django's staticfiles system
Try using the {% static %} tag for your icon. This will help make deployment easier, especially if you use a separate CDN from your webserver. There's lots of literature on how to set up staticfiles for Django projects in production, it's a large topic, but you'll be able to approach it more easily if you use the {% static %} tag from the beginning.
Optional suggestion: Django's URL routing system
Your route in index.html is hard-coded to be "/". Django has a powerful URL referencing system to leverage. If you've defined the root URL / using Django too, you can refer to it by name. Docs: {% url %}, and for the back-end, reverse().

Using Nunjucks in flask app - Trying to include HTML

I'm using Nunjucks apart from Jinja2 in my Flask application so I can pass in some variables through JS that I want to render in an HTML template.
-- Here's what I do --
JS controller:
this.element = DomHelper.htmlToDom( slideTemplate.render({ slide : this.model }));
{% include "presentation/slide/layouts/layout-1.html/" %}
What I have working:
Nunjucks compiles & render works properly without the {% include..}
slide variable is being passed and used fine
Any thoughts or suggestions would be nice. Thanks!
So I found that I had overlooked a simple thing. My nunjucks was configured to work only for the client side but the templates are served through flask. The relative path will only work for the client side data.
Solution: I placed the template layouts inside the static/ directory instead of in server-side templates/
Based on your question, you might have a typo. You have:
{% include "presentation/slide/layouts/layout-1.html" %}
but you say:
The desired html template I want to includes is in
templates/presentations/slide/layouts/ - Here's my folder structure
Is the path templates/presentations OR templates/presentation ?

Why does using a variable in settings.ALLOWED_INCLUDE_ROOTS won't let me use {% ssi %}?

Problem
I'm using Django 1.3. I will have to use many different JavaScript functions (like 10 or something) in my template.
What I first did was to put them in the <script> tag, which worked fine. But now that it works, I want to separate them from the template code. It would make the code way more read'able.
So I thought of using the {% ssi "..." parsed %} thing. Since I use Django template tags in my JavaScript code, I can't just link them from my static files with <script src="..."></script>.
Here is what works :
# This will allow the {% ssi %} tag to include files from the given paths
ALLOWED_INCLUDE_ROOTS = (
'/THIS/IS/THE/FULL/PATH/TO/MY/PROJECT/static/js/',
)
Here is what does not work :
# Project root for further paths
PROJECT_PATH = os.path.dirname(__file__)
# This will allow the {% ssi %} tag to include files from the given paths
ALLOWED_INCLUDE_ROOTS = (
PROJECT_PATH+'/static/js/',
)
I double-checked that the two strings were the same (with ./manage shell) and they are exactly the same (with trailing / and all).
Questions
Why does the second code renders me [Didn't have permission to include file] in my template ?
Also, how should I link the file to include in the {% ssi %} tag ? Since {% get_static_prefix %} does not work, I'm currently using the file's full path, which is ugly.
As odd as it may appear, I didn't make any change in my settings.py but it is now functionnal. I believe Mike Cooper was right and some remote code was breaking ALLOWED_INCLUDE_ROOTS path.
ALLOWED_INCLUDE_ROOTS is likely a constant due to it's naming convention. Constants aren't meant to be variable.
http://en.wikipedia.org/wiki/Constant_(programming)#Naming_conventions

How can two apps respond to the same URL in Django?

I think I'm missing a basic concept here. In the stereotypical Django project, you'd have two apps responding to different urls:
http://localhost/myproj/app1/33
http://localhost/myproj/app2/newcomment.html
But what mechanisms exist to handle cases where the two apps are complementary - say one provides content, and the other provides presentation? Or maybe one is content and the other is a kind of static, side-wide content that should appear on every page.
In particular, I don't understand how both apps can use template inheritance to extend the same template. Imagine there's a base app "baseapp" with a template "base.html":
...
<div blah blah>
{% block content %}
{% endblock %}
...
App1 extends it:
{% extends "baseapp/templates/base.html" %}
{% block content %}
... here's the actual content...
{% endblock %}
App2 adds a little banner or something:
{% extends "baseapp/templates/base.html" %}
{% block content %}
<div class="banner">Please support our site!</div>
{{ block.super }}
{% endblock %}
So what are the ways that both templates can get displayed? I can think of:
app1 could extend app2's templates. But this seems wrong: app1 is the content provider, and shouldn't be dependent on something as trivial as app2.
app2 could extend app1's templates. But this seems wrong: now the URL scheme would have to funnel every URL through app2 (if I understand correctly)
middleware?
As I said, I'm probably missing something very basic. Or I'm making some very faulty assumptions that I don't know about. (This question is my third attempt, after Embed an optional Django application in another page, if that app is present and How to capture and display information external to my webapp, but relevant to users of it? - I'm having trouble framing the issue.)
App doesn't respond to an URL, a view does. View is a function that can use models, forms and other object from any app. There isn't any problem here.
If you want to add something to template, inheritance isn't the only way. You'd better use custom context processor or custom template tag.
I think what I was actually missing here:
Apps can override templates just by including a template of the right name in the right subdirectory. The Django docs don't make this very clear, that I can see: they refer to this functionality in the context of Admin templates
When overriding a template as above, you can't extend it, but:
This snippet lets you both override a template and extend it: http://djangosnippets.org/snippets/1376/
Here's a closely related question: Django: Overriding AND extending an app template

gae_mini_profiler {% profiler_includes %} gives Invalid block tag: 'profiler_includes'

I am attempting to install gae_mini_profiler in my django-nonrel app
I placed the {% profiler_includes %} tag at the bottom of my base.html
It results in a
Exception Type: TemplateSyntaxError
Exception Value: Invalid block tag: 'profiler_includes'
I placed
from gae_mini_profiler import profiler
application = profiler.ProfilerWSGIMiddleware(application)
at the bottom of djangoppengine/main/__init__.py
I followed all the other instructions at https://github.com/kamens/gae_mini_profiler#start
What am I doing wrong?
I solved this by changing gae_mini_profiler/templatetags.py to be a true template tag library.
To do this create a package called templatetags, and then move(and rename) the templatetags.py module to profiler_tags.py.
Inside of profiler_tags.py make the following changes:
Change:
from google.appengine.ext import webapp
register = webapp.template.create_template_register()
To:
from django.template import Library
register = Library()
Change:
path = os.path.join(os.path.dirname(__file__), "templates/includes.html")
To:
path = os.path.join(os.path.dirname(__file__), "../templates/includes.html")
In your settings file add gae_mini_profiler to your list of installed apps.
Remove all references to
template.register_template_library('gae_mini_profiler.templatetags')
In your templates whereever you had {% profiler_includes %} you then need to add a load block
{% load profiler_tags %}
I think that is all of the changes, but need to go check my git log.
Are you using the new Python 2.7 runtime for GAE? If so, the django template setup is slightly different and gae_mini_profiler hasn't been upgraded yet (anyone is welcome to submit this fix, haven't gotten to it yet).
It should be easy to work around as the only thing you need to do is find a way to render the HTML string returned by gae_mini_profiler.templatetags.profiler_includes() anywhere in your page. There are a number of methods of accomplishing this if the built-in template tag isn't working as-is. You could simply call the function in your base request handler and pass the resulting html into your base template if absolutely necessary (although this is admittedly a gross hack).
We'll hopefully have Python 2.7 working w/ gae_mini_profiler shortly. If you're not on Python 2.7, I'm not sure what the issue is as I'd expect the current code to work...