How does a django render function know where this file is located? - python

Right so I am following a long a python Django tutorial and I am confused on how this
render function knows where index.html is. The file I am in is views.py.
from django.shortcuts import render
from appTwo.forms import NewUserForm
def index(request):
return render(request,'appTwo/index.html')
The file structure looks like

It doesn't "know" per se, but it does scan all template directories you list in settings.py as described here. The first that matches the name you provide is used.

Related

How to render in template in Django?

I am trying to display my data on the HTML file but I am unable to display, I have a function in views.py file and i render this function data on my HTML file, but it's not going to the HTML path, please let me know how I can display data in Django default template.
Here is my app appname and its have a views.py file and this file has a function that displays my data on the HTML page...
please have a look at the views.py file...
def mydata():
var1=Mymodel.objects.all()
template_name='../templates/admin/appname/modelname/change_list.html'
context={'var1':var1}
return render(request, template_name, context)
Note: this template folder is that which Django provides in default, it's not available inside my app (appname), it's available outside of my app
so main issue is in thsi path template_name='../templates/admin/appname/modelname/change_list.html', because it's getting the correct path
Create folder templates inside you app, put there template.html. Then in views.py:
def mydata(request):
you code
return render(request, 'template.html', locals())
locals will collect all variables that you created inside function.

get_context_data variable doesn't show up at HTML file

I have just started with using Django with a Django Crash Course book and got stuck on a part.
Let me show you what I have done so far and where I got stuck.
I opened a templates folder on the hellodjango project folder and wrote some basic HTML code like this.
<h1>Greetings</h1>
<p>Hello, world!</p>
<p>{{my_statement}}</p>
Here, the book says that it is okay to write my_statement like this because it will be later understood in python.
Later on it tells you to change views.py file under the homepage folder like this.
from django.views.generic import TemplateView
class HomepageView(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['my_statement'] = "Nice to see you:"
return context
However, when I refresh the page my_statement variable doesn't show up on the webpage at all. What could I possibly be doing wrong? I think if I didn't didn't have the packages, an error would pop up? But errors don't show up as well.
I have also checked the django documentation on this topic but the code here has similarities to the one I am working with.
Thanks for your help.

What is the difference between render() of DjangoTemplates class and render() method found in django.shortcuts module?

I am trying to learn Django. I am creating a small applicationt to understand its basic functionalities. In views.py of a django app, some tutorials use render() from template while others use render() from django shortcuts module.
For instance, in views.py
from django.shortcuts import render
def home(request):
context = {}
template = "app/add_item.html"
return render(request, template,context)
and yet others,
from django.http.response import HttpResponse
from app.models import Items # this is the model
def home(request):
item_list = Items.objects.order_by('-item_name')
template = loader.get_template('app/add_item.html') # could be index.html as well
context = {
'item_list': item_list,
}
return HttpResponse(template.render(context, request))
What is the difference between render() method of DjangoTemplates class and render() method found in django.shortcuts module? Which one should I prefer and why?
django.shortcuts.render is, as its name implies, a shortcut for returning a rendered template as a response from a view. Its use is rather limited to that context. It takes an HttpRequest instance as its first argument and its main purpose, per the docs, is to
combine a given template with a given context dictionary and returns an HttpResponse object with that rendered text.
Importantly, this selects a template by name. It is intended to select a template for rendering and returning as a response.
Template.render is part of the low-level template API and takes the single template, represented by that object, and renders it to a string.
Importantly, this takes only the template already represented by your object. It has no mechanism for discovering another template to render.
Generally, the shortcut version is the most useful, as quite often you want to return a rendered template as a response from your views. This is the whole reason it exists.

Get the source of a Django template

I need to get the source of a template. I looked into the template APIs and into the source code with no success.
Apparently, the Template object keeps no reference to the original source.
Before messing up my codebase I'm asking: is there a simple way to get the source of a template?
The Template objects don't keep a reference to the original source, but they do keep a reference to the original source file and you can re-read the source from there:
source = open(template_instance.origin.name, 'r').read()
If you know exactly what loader is loading template you can use Loader method directly.
from django.template.loaders.app_directories import Loader
source = Loader.load_template_source(file_name)[0]
file_name is same as when loading templates with loader.get_template(file_name)
There is a great shortcut called render_to_string.
As de docs says:
It loads a template, renders it and returns the resulting string:
from django.template.loader import render_to_string
rendered = render_to_string('my_template.html', {'foo': 'bar'})
So, the variable rendered is a string with the source code of the template
Templates are text files (usually, HTML, but not necessarily) that get rendered with a context (usually) when called from a call to, for instance, django.shortcuts.render. If you have a view function, that should specify which template it's using.
From the docs:
from django.shortcuts import render
def my_view(request):
# View code here...
return render(request, 'myapp/index.html', {"foo": "bar"},
content_type="application/xhtml+xml")
Here, the template would be "templates/myapp/index.html".

Get template name in template tag ( Django )

is there a way to get the template name ( being parsed ) in a template tag ?
I have read searched and found nothing, only this previous post
Getting the template name in django template
which doesn't help me much, since the answer relies on settings.DEBUG being true, which in my case can't be.
I don't really know where to start on this one, so any suggestion is welcome :)
EDIT
So basically what i want is to create a plugable tag that when rendered it checks for a Tag object, this would be the source for the tag object
class Tag(models.Model):
template = models.CharFIeld(max_length=50)
name = models.CharField(max_length=100)
plugins = models.ForeignKey(PluginBase)
if theres a tag object, then it displays all plugin objects, if not it creates a tag object unique to the name provided in the template tag and the template name, if getting the template name is not possible, then i guess i can just make it unique per name. The whole tag is kinda like a placeholder, for those familiar with django-cms
You could perhaps do this with a context processor, but I'm not sure if these have access to the name of the template.
What will work is to make a wrapper for the rendering calls you do. Say you currently do the following:
from django.shortcuts import render
def index(request):
return render(request, 'app/index.html', { 'foo': 'bar', })
If you create your own wrapper for this, you could add the template name to the dictionary before the actual render takes place:
from django.shortcuts import render
def myrender(request, template, dictionary):
dictionary.update({'template_name': template})
return render(request, template, dictionary)
Then in your views, change it as follows (assuming you saved the above function in myutils.py, and it is available on your path):
#from django.shortcuts import render <- delete this line
from myutils import myrender as render
def index(request):
return render(request, 'app/index.html', { 'foo': 'bar', })
Now all your render calls will update the dictionary with the template name. In any template, then just use {{ template_name }} to get the name. You can of course also update other rendering function like render_to_response and such in a similar fashion.
Also, the import myrender as render might or might not confuse you later on because it is named like the Django function... if so, just import it without the "as render", and replace all render calls with myrender. Personally I'd prefer this since this makes it a drop-in replacement for the existing rendering functions.
Looking at the source, while the Template object would have access to the template name (via .name) this value is never passed on to the Parser object and therefore not available to template tags.
There are various ways of making the template name available to the template itself (by adding it to the context) but not within the template tags.
As Daniel Roseman mentioned in the comments, if you can elaborate on what you're actually trying to achieve, there may be a better way to achieve what you want. No offence, but this sounds like it may be an XY problem.
Out of academic interest, I had a quick fiddle to see if it was possible. As far as I can see, it is possible but not without changing or monkey patching the django source.
Note: the following is not a recommended solution and merely hints at what may be required to actually make this work. Not to be used for production code.
By modifying django.template.base.py with the following changes, we add the .template_name attribute to the parser object making it available to template tags.
Added optional arg to compile_string
Added template name as extra attribute to parser
Passed in the template name when calling compile_string()
To test this out, I defined the following tag which simply returns the template name in caps:
from django.template.base import Node, Library
register = Library()
class TemplateNameNode(Node):
def __init__(self, template_name):
self.name = template_name
def render(self, context):
return self.name.upper()
#register.tag
def caps_template_name(parser, token):
return TemplateNameNode(parser.template_name)
and the following template:
{% load mytags %}
Template name in caps: {% caps_template_name %}
This seems to work when tested in ./manage.py shell:
>>> from django.template import loader, Context
>>> t = loader.get_template("test.html")
>>> t.render(Context({}))
u'\nTemplate name in caps: TEST.HTML\n'
While this seems to work, I should reiterate that manually patching the django source never a good solution and is subject to all sorts of misery when migrating to different versions.

Categories