I have a link in a layout template that another template extends. i want the link to pass in a variable thats in the template that extends the other. I want to pass the name variable in the documentPage template through the editDoc link in the layout template. can anyone think of a way to do this? thanks
In views.py file, you can pass the link as a context dictionary to template:
def function_name(request):
generated_link = 'generated_link'
context = {
'link': generated_link
}
return render(request,"documentPage.html",context=context)
You can extends template as :
{% extends 'layout.html' %}
{% block body %}
# Write body here
Click Me
{% endblock %}
Related
I'm trying to extend a base template in Django named 'base.html' in my main page 'index.html' and it does not work as expected. Rather than extending the template, the page just displays {% extends 'base.html' %}, plus the HTML in index.html when displaying the index page.
The 'base.html' page sits in the root of my templates folder and my 'index.html' page sits in templates/pages.
In 'base.html':
{% load static %}
...some code...
{% block content %}
{% endblock %}
...some code...
In 'index.html':
{% extends 'base.html' %}
{% load static %}
{% block content %}
...some code...
{% endblock %}
In views.py:
def index(request):
return render(request, 'pages/index.html')
In settings.py:
TEMPLATES = [{'DIRS': [os.path.join(BASE_DIR, 'templates)]
Expected Result:
Navbar
Content
Actual Result:
{% extends 'base.html' %}
{% load static %}
{% block content %}
Content
{% endblock %}
Like others mentioned, you are most likely viewing the html file directly.
You need to go to a view that makes use of the template which will render the final html.
I am not familiar with your project structure, so try doing this first:
in urls.py
from django.urls import path
from django.views.generic import TemplateView
urlpatterns = [
path('', TemplateView.as_view(template_name='index.html'))
]
and copy your index.html to the root of your templates folder.
then browse to http://localhost:63342, once you have it working, then you can work your way out to suit your project structure.
Not opening the base.html template. The view function points to the the child data file. When I remove the extends statement from that, the child block data displays. So it is that Django is not interpreting the extends statement in the data file correctly when it exists. I can find no discussion of what might cause that to happen. And no error messaging. Kind of makes a deal breaker out of django.
You are probably opening the template itself rather than calling the development server. If Django has a problem with any of those things, it throws an error. It does not spit out the template code.
I would like to have a template that extends another conditionally. Basically, when a variable called "ajax" is true I DO NOT want to have the template extend another.
{% if not ajax %}
{% extends "/base.html" %}
{% endif %}
Any clues?
While you may not wrap extends in logic blocks, since it must be the first tag if used, it can still accept variables, including filters. This should fit your purpose nicely:
{% extends ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}
Note: the yesno filter also accepts null values (None) as the third choice, and if you do not specify one (as in this case), it will fallback to converting it to False (i.e. it will return the second choice). This allows you to not specify the ajax variable in your template without breaking it.
Suggested by user Rafael:
{% extends request.is_ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}
This will only work if you are using a RequestContext context instead of a plain Context object and you have the request context processor enabled, or alternatively, if you insert the request object in your template context.
You cannot do it like that. You can however set a variable and use that to choose the template to extend:
{% extends my_template %}
Then in python code you write something like:
if ajax:
template_values['my_template'] = 'base_ajax.html'
else:
template_values['my_template'] = 'base.html'
You may wish to refer to the documentation for more information.
I was looking for the solution of the same problem and came with a bit better workaround than suggested by Klaus Byskov Hoffmann. It is better because you don't have to have 2 separate base templates for ajax and non-ajax requests and, which is more important, you don't have to define if statement that will define which base template to use in EACH controller.
In your case the solution would be:
page.html
{% extends "/base.html" %}
{% block body %}
hello world
{% endblock body %}
base.html
{% if not ajax %}
<html>
<head></head>
<body>
LOGO and other stuff...
{% endif %}{% block body %}{% endblock body %}{% if not ajax %}
FOOTER
</body>
</html>
{% endif %}
So, base.html is always included but it prints its content only when not ajax.
UPDATE: This can be simplified by creating and adding a new ConextProcessor that will populate ajax context variable from the HttpRequest.is_ajax(), so you don't have to do anything extra in your controllers and templates at all.
If you don't want to "extend" a parent template, you can always create an empty file called null.html and extend that. Kind of hacky, but easy to understand.
I know this is an old thread but in case someone stumbles across this, I believe the best way to achieve your goal would be:
"views.py"
if ajax:
request.session['ajax'] = 'ajax'
"base.html"
{% if 'ajax' in request.session %}
{% include "ajax.html" %}
{% endif %}
and in "ajax.html" you wouldn't use any {% extends %} or {% block %} tags since you won't be calling anything for "ajax.html" to extend onto the base. That will be taken care of by "include".
One of my tables in my app is called Gallery and I have the following class to list all of the objects on that table:
from django.views.generic import ListView
from galleries.models import Gallery
class GalleryList(ListView):
template_name = "path/to/template"
context_object_name = "object_list"
def queryset(self):
return Gallery.objects.order_by('-title')[:20]
And it does the job. On my template I do the following:
{% block gallery_list %}
<h1>Gallery List</h1>
<ul>
{% for gallery in object_list %}
<li><img src="{{ gallery.thumbnail.url }}" />{{ gallery.title }}</li>
{% endfor %}
</ul>
{% endblock %}
Everything works as expected. The thing here is that on my base.html template I have {% block title %} for the meta title tag, {% block description %} for my meta description tag in the header. And I want to be able to declare it somewhere and pass it to the view. To be clear, the variables title and description are strings (ex: title="List of all galleries on website").
On the view I want to do something like:
{% extends "base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block description %}{{ description|default:title }}{% endblock %}
But, on the class GalleryList I don't know where to declare the variables title and description. I don't know if that's possible or proper for Django. I want to do what's right.
Also, as I have a costume template for listing all the galleries I could just do:
{% extends "base.html" %}
{% block title %}List of all galleries on website{% endblock %}
{% block description %}List of all galleries on website...{% endblock %}
But then again, I don't know if that's proper for a well coded Django app. I'm a beginner with Django and I would like to know what's the way to go about this. Hope my question is clear enough.
You can override the ListViews get_context_data method to add whatever additional context variables to you want to the context:
class GalleryList(ListView):
def get_context_data(self, **kwargs):
ctx = super(GalleryList, self).get_context_data(**kwargs)
ctx['title'] = 'My Title'
ctx['description'] = 'My Description'
return ctx
The other approach - of having a template that fills in this information - is also sound. Which is better really depends on how dynamic the data is. If the title/description is based on model data or some other factors, then it makes sense to set it in the view. If it is fixed for a particular template then it is probably cleaner to put in in a template that extends base.html.
I'm trying to build a website that has products and categories.
When you are on the page of a product, you can click a button to see a list of all the categories it falls under.
You can click another button, that appears on all pages, to see a list of all the categories overall.
In the html page see_all_categories, I wrote a simple block like this:
{% extends 'base.html' %}
{% load staticfiles %}
{% block content%}
{{Category.all}}
{% endblock content %}
I expect to see a messy printout of all the categories but I don't. It doesn't return an error, but it produces nothing, other than the base.html.
What am I doing wrong?
You want to display a list of the categories. I assume your Category model owns an attribute named "title" which is the representation of your Category.
If you're using Django template engine or Jinja2, you can make a for loop inside your template like this :
{% for cat in Category.objects.all %}
{{ cat.title }}
{% endfor %}
As a troubleshooting, I'd suggest you didn't pass your Category model to your template, that is not done automatically. You have to add your model to the context before rendering the template.
As mentionned in the comments, here is doc for template rendering with Django templates.
Django Template Guide
To add your model to the context you can follow this guide.
I don't intend to help you further because I lack of information and that may vary a LOT according to your settings. (Class Based views ? Function based views ? What kind of template are you using... And so on)
I figured out the solution after many long annoying hours of trying everything. I feel dumb but I want to spare the next guy the massive pain in the two-pack.
This is what I did:
In the Views.py, I changed the view function for this page FROM this:
def view_all_categories(request):
context = {'Category' : Category}
return render(request, 'store/see_all_categories.html', context)
TO this
def view_all_categories(request):
all_cats = Category.objects.all().order_by('id')
context = {'all_categories' : all_cats}
return render(request, 'store/see_all_categories.html', context)
and in the page see_all_categories.html itself, I changed it (from the question) TO this:
{% extends 'base.html' %}
{% load staticfiles %}
{% block content%}
{% for cat in all_categories %}
<p>{{ cat.name }}</p>
{% endfor %}
{% endblock content %}
And now it works!!
I would like to have a template that extends another conditionally. Basically, when a variable called "ajax" is true I DO NOT want to have the template extend another.
{% if not ajax %}
{% extends "/base.html" %}
{% endif %}
Any clues?
While you may not wrap extends in logic blocks, since it must be the first tag if used, it can still accept variables, including filters. This should fit your purpose nicely:
{% extends ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}
Note: the yesno filter also accepts null values (None) as the third choice, and if you do not specify one (as in this case), it will fallback to converting it to False (i.e. it will return the second choice). This allows you to not specify the ajax variable in your template without breaking it.
Suggested by user Rafael:
{% extends request.is_ajax|yesno:"base_ajax.html,base.html" %}
{# stuff #}
This will only work if you are using a RequestContext context instead of a plain Context object and you have the request context processor enabled, or alternatively, if you insert the request object in your template context.
You cannot do it like that. You can however set a variable and use that to choose the template to extend:
{% extends my_template %}
Then in python code you write something like:
if ajax:
template_values['my_template'] = 'base_ajax.html'
else:
template_values['my_template'] = 'base.html'
You may wish to refer to the documentation for more information.
I was looking for the solution of the same problem and came with a bit better workaround than suggested by Klaus Byskov Hoffmann. It is better because you don't have to have 2 separate base templates for ajax and non-ajax requests and, which is more important, you don't have to define if statement that will define which base template to use in EACH controller.
In your case the solution would be:
page.html
{% extends "/base.html" %}
{% block body %}
hello world
{% endblock body %}
base.html
{% if not ajax %}
<html>
<head></head>
<body>
LOGO and other stuff...
{% endif %}{% block body %}{% endblock body %}{% if not ajax %}
FOOTER
</body>
</html>
{% endif %}
So, base.html is always included but it prints its content only when not ajax.
UPDATE: This can be simplified by creating and adding a new ConextProcessor that will populate ajax context variable from the HttpRequest.is_ajax(), so you don't have to do anything extra in your controllers and templates at all.
If you don't want to "extend" a parent template, you can always create an empty file called null.html and extend that. Kind of hacky, but easy to understand.
I know this is an old thread but in case someone stumbles across this, I believe the best way to achieve your goal would be:
"views.py"
if ajax:
request.session['ajax'] = 'ajax'
"base.html"
{% if 'ajax' in request.session %}
{% include "ajax.html" %}
{% endif %}
and in "ajax.html" you wouldn't use any {% extends %} or {% block %} tags since you won't be calling anything for "ajax.html" to extend onto the base. That will be taken care of by "include".