Django: using html templates TemplateDoesNotExist - python

I've been writing my first Django app and hit a problem with using templates.
No matter how I format the url for the template I receive the TemplateDoesNotExist error.
My html is nest in views/ with the core template being views/template.html.
I have tried:
myapp/views/template.html
views/template.html
templates/views/template.html
<full path to app>/<all variations>
None of which can locate the template.
I understand the TEMPLATE_DIRS variable may be set at project level but this is app-specific and the views/ directory is not purely for templates.
I don't think I should add to the url_patterns since the template shouldn't be accessible directly.
I've got this far without them but need to clean up the app.
Any advice?
Edit:
The only line in my controller currently is:
template = loader.get_template("test/templates/test/template.html")
The line has been tested with every variation mentioned above and the one from the first comment.
There are no additional lines added to the urlpatterns, as I understand it adding to here would open access up to the public via url.

it should be:
template = loader.get_template("test/template.html")

Related

How do I override this pattern? django

I'm trying to override the template located in the forms/templates/django/forms/widgets/input_option.html directory, but it's not working for me. Is it possible to do this at all?
You need to create the same template path django/forms/widgets/input_option.html in any of your INSTALLED_APPS.
Django will iterate over all INSTALLED_APPS and look for a template with the given path, django/forms/widgets/input_option.html in your case. The last found file will be used as the template for rendering.
You can find an example and explanation in the django documentation: https://docs.djangoproject.com/en/4.0/topics/templates/#django.template.backends.base.Template.render

Django template is not changed after update (possible cache)

I have a problem with Django. Possibly with it's cache. Version 1.11
I use template in urlpatterns like :
urlpatterns = [
url(r'^service_preview/', include(serviceprev_urls, namespace = 'service_preview')),
url(r'^service_preview/',TemplateView.as_view(template_name='service_preview.html')),
]
After a lot of updates, applied to my template, the changes stop appearing in user's browser. I have actual template in my templates folder and some previous version when preview source code in browser. If I rename the template (this should raise error because template is absent), I still have that previous template in browser source. Browser page refreshing, clearing browser cache etc does not help. There are no duplicates of this page in my template folder.
When I use another template, all is ok.
Possibly, problem is in django cache. I don't know how to force clear cache, maybe it would be a solution.
I put this at app setting file, but it doesn't help.
CACHES = {'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache',}}
EDIT:
i found i have duplicate html name, located in the same project, but other application's template directory. May it cause a problem
By default, the Django template loader caches templates when DEBUG = False. After changing a template, you need to restart the server (e.g. Apache or gunicorn) to see the changes. This behaviour is not affected by the CACHES setting.

Elegant way to namespace templates in Django

Django tutorial suggests to organize templates like this:
Within the templates directory you have just created, create another directory called polls, and within that create a file called index.html. In other words, your template should be at polls/templates/polls/index.html. Because of how the app_directories template loader works as described above, you can refer to this template within Django simply as polls/index.html.
Tutorial also tells what happens if I just put index.html in polls/templates:
Now we might be able to get away with putting our templates directly in polls/templates (rather than creating another polls subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.
My assumption was that as long as I'm creating an isolated application, it's templates are also isolated from other apps without any subfolder magic.
Is there another way to namespace, so I can refer to template as index.html without creating duplicated folders?
The way templates are organised in a Django project is very flexible. So there's nothing to stop you ordering the template files however you want, as long as you specify the correct template name in the view. For example, you could use a Class Based View for the list of Polls, specifying the template_name as whatever you like:
# polls/views.py
from django.views.generic import ListView
from .models import Poll
class PollList(ListView):
model = Poll
template_name = 'any/path/you/choose/any_name.html'
Having said that, it's good to create a consistent template structure to keep the code maintainable. I'd recommend at the very least keeping your page-level templates (things which are used to return the whole html page) structured in folders with their relevant app name, and anything you include (snippets included with the {% include %} tag) within includes subfolders, like so:
templates
- base.html
polls
- poll_list.html
includes
- poll_votes.html
Edit:
If you still need namespaces despite this, you could use URL namespaces.

Django wrong precedence of templates?

It took me forever to find out why a template was not getting overridden, only to find that it seems Django simply does not use the correct precedence in overriding the templates.
The templates I'm trying to change are the ones for changing the user's password, which are loaded for the URL /accounts/password/change.
I have my modified templates in mysite/myapp/templates/registration; the system default templates are at /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/templates/registration. When templates are present in both these directories, Django uses the system (/Library) ones. Huh?
When I remove the templates in /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/contrib/admin/templates/registration
, the correct ones (i.e. mine, in mysite/myapp/templates/registration) are loaded.
How to fix this issue? That is, how to make Django load my overridden templates without having the delete the original templates found in the /Library?
you have to create an admin directory inside the templates dir in which you set the templates you want to override
In order to override one or more of them, first create an admin directory in your project’s templates directory. This can be any of the directories you specified in TEMPLATE_DIRS.
Read the Django doc here

Using external URLs in Django's TEMPLATE_DIRS

Django's TEMPLATE_DIRS in Settings.py calls for unix style slashes.
Because of this, when I call
get_template('some/template.html')
in a view, the result always starts at the root, and results in a call to
/home/username/projectname/public/some/template.html
The problem is that I'd like to use templates hosted on an entirely different site. This works fine for other Settings.py fields (MEDIA_URL and STATIC_URL), where it will take an absolute http path with no objection.
Given an http path,
TEMPLATE_DIRS ('http://example.com/',)
in Settings.py will force
get_template('some/template.html')
in a view to try and find
/home/username/projectname/public/http://example.com/some/template.html
I've tried to circumvent this like so
TEMPLATE_DIRS ('../../../../http://example.com/',)
But it still forces a leading slash, so I get "/http://example.com", which is useless.
My questions:
Is there a way to trick this into pulling the template files from
another server?
Is that even feasible, given that the template files need to be
processed for the view?
Is it possible to create an alternate to 'django.template.loaders.filesystem.Loader' that doesn't call for unix style slashes?
You don't need to use the template directory is you dont want to. If you have a server that is serving template files, you can simply fetch them remotely using urllib2 and create and render the template with a context manually:
import urllib2
from django.template import Context, Template
tpl_html = urllib2.urlopen("http://mysite.com")
tpl = Template(tpl_html)
return tpl.render(Context({
'some_variable' : 'some_val',
})
If you are going to do this, you have to incorporate some caching, as for every request to using this template, you need to make an external request. Alternatively you could write this into a custom loader but it will suffer the same limitations.
You can't do this.
It has nothing to do with path names. It's just that the filesystem template loader needs to load things from the filesystem, hence the name.
This is completely different from the case of MEDIA_URL: that simply adds a path into your HTML, which your browser then loads. Django doesn't care where that file lives: although in fact the opposite applies, in that if you pass it a filepath that isn't a URL (ie served by a webserver somewhere), it simply won't work.
Now, you could write a template loader that gets its templates from another server. Template loaders are pluggable - you just need to put the name of your new loader in the TEMPLATE_LOADERS setting. The loader itself would need to use something like urllib.urlopen to get the template from the external server.
But think very carefully before you do this. This means that every single template request now requires a call to an external server before you can serve the page. In the typical case of a template that extends other templates and includes calls to included template tags, that might be five or ten calls. And, unlike media files, it can't be done in parallel: the page simply won't be served until the whole process is finished. This is likely to make your webserver very very slow.
I don't know why you think you need to do this. Templates are part of your application code, so they would normally live on the same server as your Python code. If you really have some reason to keep them externally, one solution might be to mount the external filesystem onto your webserver via something like sshfs. It's still likely to be very slow though. Think again.
No - it's not possible to trick it into pulling files from another server via http
Yes - you certainly could subclass django.template.loaders.filesystem.Loader (and by altering the load_template_source method appropriately) so that you could load templates via http
Once you had done 3 then the answer to 2 would be yes - it would be feasible - ultimately Django's template language doesn't care where it gets the file from, as long it's in the right format.
However, it seems like a very inefficient way of loading templates and more likely there is a much better way of achieving the same result.

Categories

Resources