What is the difference between {% placeholder content %} versus {% block content %}{% endblock %}? - django

Exactly the question title. What are the differences between the purpose of each code and how Django CMS renders the content?

{% block content %}{% endblock %} is part of Django. It means you can override the contents of that code in a template that derives from that template. So once you've done that, the contents of the block have been changed but that is it - you'll simply see what the contents of the applicable block called content are.
{% placeholder content %} is part of Django CMS. It allows you to define sections on the page where you can place Django CMS plugins. This means Django CMS will detect where these placeholders are and it allows an administrator to specify what plugin goes into which placeholder. The difference with {% block content %}{% endblock %} is that you can change the contents at any time by going to the admin page and selecting a different plugin for that placeholder.

Related

django navbar template - tags

I have created 2 navbars one for blog and one for the main app. I use include tag to introduce navbar into templates. "extends base.html" is also used however, navbar is not included in the base file and as mentioned above is introduced as include tag.
In the main app which is supposed to render same navbar(contents) for all pages of the app is not doing so, and I only receive the desired result on the homepage.
The context variables used on the navbar are from the homepage view function and when homepage page is rendered it works perfectly however when I open any internal pages of the same app the navbar does not show any of the content.
I presume navbar would try and load context variables of the view function of the active(currently opened) html page only and so homepage context variables do not work on any other page, even though navbar is a separate html file.
If this is correct I wanted to know how to get around it as all the pages on the main app should show the same navbar values.
home.html - This is how base and navbar are introduced in the template.
{% extends 'base.html' %}
{% block title %}Title{% endblock title %}
{% block navbar %}{% include 'navbar.html' %}{% endblock navbar%}
Similarly rest of the pages introduce both base and navbar.
All context variables used in navbar {% for country in countries %} for example are from view function for the home page.
When I use the same navbar for say "about us" page the navbar does not show the required information.
Does that help?
simple way you can do
in base.html
{% block content %}
{% endblock %}
in navbar2.html file
all html code
in navbar2.html file
all html code
other1.html file
{% extends 'base.html'%}
{% blck content %}
{% include 'navbar1.html' %}
All html code here
{% endblock %}
other2.html file
{% extends 'base.html'%}
{% blck content %}
{% include 'navbar1.html' %}
All html code here
{% endblock %}
if you want send the context variables to all files then create view which will render to base.html and pass that context variables to base.html. As base.html is extended in each templates, so you will get access for that context variables in all templates

Django - Dynamically include JS/CSS based on installed apps

Does anybody know a way to adjust the included JS/CSS resources in a template based on the apps you've installed?
Let's say we have a basic feature in app x using template.html, and this requires foo.js which is provided in the static files for the app.
What I'd like is a way of saying an additional and optional app y can register bar.js to be included in template.html as well and this provides some advanced functionality.
Ideally, this should be tied in on a feature level - so I register both foo.js and bar.js to provide for feature A and in my template I just indicate I want all the static content for A.
You can follow the django admin framework approach. In your base template have an extra section for style and javascript. Based on some condition you can insert the new files.
For Example:
Define these two blocks in your base template
{% block extracss %}{% endblock %}
{% block extrajs %}{% endblock %}
If you want to add a js or css based on some condition, you can add a check inside
{% block extracss %}
{% if new_app_installed %}
# Insert your CSS
{% else %}
# Default
{% endif %}
{% endblock %}
You can also check if your plugin app is installed and pass this context variable from view to template.
from django.conf import settings
if "new_app" in settings.INSTALLED_APPS:
is_new_app_installed = True

Django Tutorial: Templates and Views

I'm in the process of completing the official Django tutorial and I'm stuck on part 3. Since templates are also used in the last part of part2, I will describe what I did:
Part 2 told me to "copy the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into an admin subdirectory of whichever directory you're using in TEMPLATE_DIRS."
So I created a new directory "admin" that has the following relative path (note that where Django uses the directory name 'mysite', I use 'django_test' : /django_test/polls/templates/admin. I copied the base_site.html file into this directory.
When I render the file in my local browser, it says: {% extends "admin/base.html" %} {% load i18n %} {% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %} {% block branding %}{% trans 'Django administration' %}{% endblock %} {% block nav-global %}{% endblock %}
Part 3 has me create an index.html file in a new subdirectory polls/index.html. But when I load this file in my web browser (using localhost server), I simply see the html code instead of a bulleted list (see below).
Note that I also edited TEMPLATE_DIRS in my settings.py file to tell Django that it can find index.html under /Users/myname/Sites/django_test/django_test/templates
Below I will paste the code that my local server renders (instead of the bulleted list, which is what I want). Do you know why this code is being rendered, instead of the bulleted list?
<html>
<head><title>Test</title></head>
<body>
{% 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 %}
</body>
</html>
I don't know whether I'm making a mistake in how I'm organizing the files. Might someone have an idea about what I'm doing wrong?
As you say in your comment, you're putting the file path into your browser. Naturally, then, you're going to see the text of the template, because you are bypassing Django completely and getting the browser to load the unrendered template from disk.
As the tutorial describes, you need to ask Django to serve the template and render it, via its normal URL mechanism. In the earlier part of that section, you went to localhost:8000/admin/ to see the admin site - this hasn't changed just because you've replaced a template. Go back to that address and you'll see your updated - and rendered - template.
The django admin site is easy once you get the hang of it.
The steps to take are:
-Uncomment the django admin site in your urls.py
-Make the css available to the admin site by either copying the admin folder (inside django package) into the folder specified in STATIC_ROOT in your settings.py or making the diectory available on your PYTHONPATH
In other words, you dont need to create a template for the admin site. You will, however, need to create templates to access the views that you create in your project

Django admin: adding pagination links in list of objects to top

Is it possible to have the pagination links that appear at the bottom of a list of objects in Django's admin interface at the top as well?
Can this be done without changing the admin templates? I suspect not, given the lack of a ModelAdmin option, but thought I'd see if anyone had done this before I dug into the template code.
I really, really don't want to have to copy and paste change_list.html into a new file, just so I can add a pagination line - that'll make changing Django versions painful, since I'll have to check if anything's changed in that file, and re-apply my change.
Do not copy change_list.html, instead create a new template that extends it:
{% extends "admin/change_list.html" %}
{% block result_list %}
{% block pagination %} {{ block.super }} {% endblock %} <!-- pagination -->
{{ block.super }} <!-- rest of results list -->
{% endblock %}
Then pass the new template's name to ModelAdmin in change_list_template attribute - doc here.
The source code implementing the django admin template for change_list.html has a content block so if you create a file change_list.html under 'admin' folder in your templates directory and add this:
{% extends "admin/change_list.html" %}
{# added pagination to top as well as bottom #}
{% block content %}{% pagination cl %}{{ block.super }}{% endblock %}
it should do the trick!

Django - Block tags in included templates get overridden by calling template

I have a template that includes another template. This included template has block tags in it.
Example:
base.html
BASE
{% block title %}Base Title{% endblock %}
{% block content %}{% endblock %}
template1.html
{% extends 'base.html' %}
{% block title %}Extended Title{% endblock %}
{% block content %}
Extended content
{% include 'include.html' %}
{% endblock %}
include.html
{% block title %}Include Title{% endblock %}
{% block another_content %}Include Content{% endblock %}
What I'm expecting is if I render template.html I should get, which I do under 1.1.1
BASE
Extended Title
Extended content
Include Title
Include Content
But I actually get this when I switched to 1.2.1 and 1.2.3:
BASE
Extended Title
Extended Content
Extended Title
Include Content
As you can see, the title block in include.html gets replaced with template1.html's title block. This replacement only happens if the block names are the same, so if I change the title block in include.html, this doesnt occur. It seems to me that it's including and extending at the same time? Anyone know if this is expected/I'm doing something wrong?
If you're not using extends in include.html then this behaviour is normal - I suppose that there was a bug in 1.1.1.
Excerpt from official documentation:
Finally, note that you can't define multiple {% block %} tags with the same name in the same template. This limitation exists because a block tag works in "both" directions. That is, a block tag doesn't just provide a hole to fill -- it also defines the content that fills the hole in the parent. If there were two similarly-named {% block %} tags in a template, that template's parent wouldn't know which one of the blocks' content to use.
Read whole thing here: Template Inheritance
If that's what you want, then the include.html should not contain any blocks at all, ie just:
Include Title
Include Content