Django mptt, extends "base.html" - django

In base.html:
<div id="menu_shop">
<input name="search" placeholder="search">
<p>Category:</p>
{% load mptt_tags %}
<ul class="root">
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</div>
in views:
def show_category_tree(request):
return render_to_response("base.html",
{'nodes': Category.tree.all()},
context_instance=RequestContext(request))
urls.py:
url(r'^category/', 'item.views.show_category_tree'),
url(r'^category/(?P<slug>[\w\-_]+)/$', 'item.views.by_category'),
How to display this in "by_category.html"
If I try(for example):
{% extends "base.html" %}
{% block content %}
{% for e in entries %}
<p><b>{{ e.name}}</b></p>
<p>{{ e.desc}}</p>
{% endfor %}
{% endblock %}
I have this error:
http://dpaste.com/810809/
{% extends "base.html" %} does not work. If I remove it, everything works.

You are seeing this error because your template context for the by_category does not include nodes.
The extends tag is related to the template, not the view. It makes your by_category.html template extend the base.html template, but it does not include the template context from any other view.
The easiest fix would be to add nodes to your template context in the by_category view.
def by_category(request, slug):
entries = Entry.objects.filter(...)
return render_to_response("base.html",
{'entries': entries,
'nodes': Category.tree.all()},
context_instance=RequestContext(request))
This would be repetitive if you want to display the nodes in lots of other views. If you want to include the nodes in all views, you may want to write a request context processor. If you want to include it in some but not all pages, then try writing a custom template tag.

Related

Failed template inheritance in django templating

I am in a middle of a project. The project uses basic html at the frontend. I having trouble in template inheritance.
This is the basic code : -
{% extends 'main.html' %}
{% block content %}
<h2>Home</h4>
<hr>
{% if request.user.is_authenticated %}
{% block home %}{% endblock home %}
{% else %}
{% for doc in doctor %}
<div>
<small>Doctors around</small>
<br>
<li>{{doc.user.name}}</li>
<br>
</div>
{% endfor %}
{% endif %}
{% endblock content %}
Also the code is extended to another template.
The child page is :-
{% extends 'rec/home.html' %}
{% block home %}
<div>
{% if request.user.usertype == 'p' %}
<h1>Hi {{request.user.name}} </h1>
{% else %}
<h1>Hi {{request.user.name}} </h1>
{% endif %}
</div>
{% endblock home %}
Both the files are in the same directory. But i have defined the templates dir in settings file in a different directory.
When i do tree /a at the templates directory this is what i get :-
Folder PATH listing
Volume serial number is 6A82-72DF
E:.
\---rec
It's just {% endblock %} you don't have to specify what block you're closing / I'm not sure you even can Wrong
That's the only issue I see with what's provided
Instead of defining the template to extend from in each template, maybe try doing something like this:
Template.html
{% extends parent_template %}
Views.py
template = loader.get_template('app/page.html')
context = {}
context["parent_template"] = "app/parentPage.html"
return HttpResponse(template.render(context, request))
This way you can assign the template from the Django side and it should be easier to troubleshoot

Django ListView not working on the template

I am trying for hours on a problem that seems very straightforward and I tried everything but it's not working. I want to display the list of blogs on a template. So, I have these views:
from django.views import generic
from .models import Blog
class BlogList(generic.ListView):
queryset = Blog.objects.filter()
template_name = 'table_of_contents.html'
context_object_name = 'blog_list'
class BlogDetail(generic.DetailView):
model = Blog
template_name = 'blog.html'
And this is the table_of_contents.html template where I want to display the list of blogs:
{% block table_of_contents %}
<p>Just for test</p>
{{ blog_list }}
{%endblock table_of_contents %}
I expect that would display the queryset string on the frontend, but that's not the case. I debugged BlogList using the Django shell and made sure that queryset was not empty.
What is the (obvious) detail that I am missing here?
Edit:
Here is the blog.html template as well:
{% extends 'base.html' %}
{% block content %}
<p>Test blog template</p>
{% block table_of_contents %} {% include 'table_of_contents.html' %} {% endblock table_of_contents %}
{% endblock content %}
Again, the querystring is not rendered at all, no matter if I use a for loop or just do {{ blog_list }}.
The queryset will look like <QuerySet …>, so that will not render effectively on the page, since it will assume that <QuerySet as a HTML tag, not as content.
What you can do is iterate over the items in the QuerySet, and render these individually, for example:
{% block table_of_contents %}
<p>Just for test</p>
{% for blog in blog_list %}
{{ blog.title }}
{% endfor %}
{%endblock table_of_contents %}
of course here I assume that your Blog model has a title field. You might need to change this to a different field.
If you define a {% block … %} [Django-doc] this means you need to inherit from a parent template that specifies a block with the name table_of_contents.
You thus need to have a parent template, for example:
<!-- parent.html -->
My page
{% block table_of_contents %}
{% endblock table_of_contents %}
in your template where you list the blogs, you thus then inherit from the parent.html page with the {% extends … %}:
{% extends 'path/to/parent.html' %}
{% block table_of_contents %}
<p>Just for test</p>
{% for <b>blog in blog_list</b> %}
{{ blog<b>.title</b> }}
{% endfor %}
{%endblock table_of_contents %}

Djang multiple levels of template extension while keeping the elements of the upper levels

I have 3 templates as following:
base.html (the top level template, as usual).
<body>
<div id="header">
...
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
category.html :
{% extends "base.html" %}
{% block content %}
<div class="category_row">
<div id="menu_category_display">
{% for category in menu_categories %}
{% with category_button="menu_"|add:category.name|lower %}
<button class="button category_buttons {{category_button}}"
onclick="showItem('{{category_button}}','category_buttons')">
{{category}}
</button>
{% endwith %}
{% endfor %}
</div>
</div>
<div class="item_row">
{% block level_2_content %}
{% endblock %}
</div>
{% endblock %}
and item.htlm
{% extends "menu/category.html" %}
{% block level_2_content %}
<div id="test_div">
{% for item in menu_items %}
<p>{{item.name}}</p>
{% endfor %}
</div>
{% endblock %}
When item.html is rendered, all the elements that were rendered by category.html are gone. Only the elements of the base.html are retained.
How do I retain all elements in all parent templates instead of just base.html? A general method to do this for more than 3 levels of extension like in my case?
Update with more detailed code for category.html. The entire category_row div does not appear in item.html. How do I retain them?
views.py
def menu_category_view(request, table_pk):
menu_categories = Category.objects.all()
menu_items = Item.objects.filter(available=True)
return render(request,
'menu/category.html',
{'menu_categories': menu_categories,
'menu_items': menu_items,
'table_pk': table_pk})
def menu_item_view(request, menu_category, table_pk):
category = Category.objects.get(name=menu_category)
menu_items = Item.objects.filter(available=True,
category=category.pk)
return render(request,
'menu/item.html',
{'menu_items': menu_items})
Folder structure: both templates sit in menu/templates/menu of app menu. However, base.html sits in root/templates (not in app menu.
Update: I have tried modifying both templates in various ways to debug. What I find is that the static content gets extended, but the dynamic content does not. So my question becomes: does Django template allow dynamic content to be extended to child / grandchild templates?
You probably don't want to use "extends" here but instead "include" to render 'item.html' within the parent document.

Django inclusion_tag contents not displaying

I cannot get the contents of an inclusion_tag to display. I am not getting an errors so i know that the tag is registering and I am almost certain that it is loading correctly. The tag is created in crudapp/templatetags/crudapp_tags.py
from django import template
register = template.Library()
#register.inclusion_tag("forum.html")
def results(poll):
form = 'blah'
return {'form': form}
templates/forum.html
{% extends 'index.html' %}
{% load crudapp_tags %}
{% results poll %}
<p>aaa</p>
{% block homepage %}
<p>bbb</p> <!-- Only this displays -->
{% if form %}
<p>Form exists</p>
{% endif %}
{% for item in form %}
<p>This is {{ item }}</p>
{% endfor %}
<div>
<p>{% if user.is_authenticated %}Add a New Topic: <span class="glyphicon glyphicon-plus"></span>{% endif %}</p>
</div>
<div>
<p>{{ totalposts.count }} posts, {{ totaltopics.count }} topics, {{ totalusers.count }} users, {{ totalviews.numviews}} views</p>
</div>
{% endblock %}
The file set up is as follows,
If you are using an inclusion tag, then the tag renders another template. You need to move the code that uses form out of forum.html and into a new template, e.g. results.html
results.html
{% if form %}
<p>Form exists</p>
{% endif %}
{% for item in form %}
<p>This is {{ item }}</p>
{% endfor %}
Then change your tag to use this template
#register.inclusion_tag("results.html")
def results(poll):
form = 'blah'
return {'form': form}
Finally, since you are extending a template, you need to move then tag into a block, otherwise the result won't be used.
{% block homepage %}
{% results poll %}
...
{% endblock %}
If you want to add an item to the template context instead of rendering another template, then you want a simple tag instead.
#register.simple_tag
def fetch_result():
result = ['foo', 'bar']
return result
Then in your template:
{% fetch_result as result %}
{% for item in result %}
<p>This is {{ item }}</p>
{% endfor %}
The {% fetch_result as result %} works for simple tags in Django 1.9+. In earlier versions, you want an assignment tag.

extend other app to my template working

I want to extend an other template to my blog.html, no matter have i try to extend this, it doesn`t work .
blog/index.html
{% block nav %}
<ul id="nav">
<li>{% block nav-blog %}Blog{% endblock %}</li>
<li>{% block nav-photo %}Photo{% endblock %}</li>
</ul>
{% endblock %}
<div class="news">
{% block polls %}
{% extends 'polls/index.html' %}
{% endblock %}
<div>
polls/index.html
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li>{{ poll.question }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Usually extends has to be stuck at the top of the template and not somewhere in the template.
In the template you use the tags that you have set up in the base templates.
You need to make sure you're doing two things here:
Declare a "nav" block in your index.html. This will let django know the part of your index html you wish to have overwritten when a template extends it. Anything you put inside the "nav" block in index html will be considered default content.
You need to use the "extends" template tag at the beginning of your blog.html so django knows the template you'd like to extend.
Like this:
index.html
{% block nav %}
<div>
Some default html here..
</div>
{% endblock %}
And then blog.html
{% extends index.html %}
{% block nav %}
<div>
This is what will render
</div>
{% endblock %}
Also, you're going to want to test index.html before trying to extend it to verify that django is finding that template. If it isn't then you need to add the directory that it is found in to the TEMPLATE_DIRS array in your settings.py file.