Django - Dynamically include JS/CSS based on installed apps - django

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

Related

Include google analytics tag to django admin without changing the template for every page

Is there a way to include the google-analytics javascript snippet easily into the django admin page ? (django 1.10)
I would like to do that without creating a custom template for each of the admin page, just insert the script in the all admin.
Thank you,
You need to override the base admin page and put the tag there. Inside Template Directory, create a folder name admin, inside that, create a base_site.html. That base_site.html might look like this:
{% extends 'admin/base_site.html' %}
{% load static %}
{% block extrahead %}{{ block.super }} google analytics codes {% endblock %}

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

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.

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!

How do include a dynamic template from another app in Django?

I currently have two apps:
app1/
app2/
templates/
app1.html
app2.html
In app1.html, I'm including app2.html:
<!-- app1.html -->
{% include "app2.html" %}
app2 has some dynamic content:
<!-- app2.html -->
{% app2_value %}
When I display app1.html, the value app2_value doesn't show up. What's the best way to handle the above in Django?
Django doesn't really process dynamic including like PHP or other languages do. Instead, you should have a base template, and use template inheritance and blocks to accomplish what you're trying to do.
So your app2.html would have the same dynamic content, but have a place for app1.html to either override or insert things.
app2.html:
{% block 'title' %}
{{ app2.title }}
{% endblock %}
{% block 'content' %}
{% endblock %}
App1's template can then extend App2's:
app1.html:
{% extends "app2.html" %}
{% block 'title' %}
Actually App 1!
{% endblock %}
{block 'content' %}
...
{% endblock %}
Unfortunately, include-handling is still new in Django and against best practices from what I've seen in the documentation and community.
In Django your views and your templates are decoupled from each other, so when you use {% app2_value %} in a template it will assume that was passed to it from the calling view.
So, to answer your question, to get that value to display, pass it to app1 template in whatever view you use to call it:
# app1 views.py
from django.shortcuts import render_to_response
import app2
def app1_view(request):
return render_to_response('app1.html', {'app2_value': app2.somevalue})
You can actually render a temple as a string and then send it to another template to be displayed. You would still need to send the variabels to the template you are rending as a string. A good use case would be to use the same template to render list or dicts in a special way.