django common templates for apps with variables - django

I want to make project-wide templates, but with app variables and app base subtemplates:
/home/project/
templates/document.html
app1/templates/app1/base.html
app2/templates/app2/base.html
And app1/views.py:
def page1(request):
document = get_document('title',app_email='test#example.com')
context = {
'document' : document,
'app_title_header' : document.header
}
return render(request,'document.html', context)
templates/document.html
{% extends app_name|add:'/base.html' %}
{% load static %}
{% block content %}
{% autoescape off %}
{{ document.body }}
{% endautoescape %}
{% endblock %}
(app_name is set by context_processors.py registered in settings.py)
def appname(request):
return {'app_name': request.host.name, 'app_base' : '{}/base.html'.format(request.host.name) }
app1/templates/app1/base.html (almost identical like app2)
{% load static app1 %} <--- difference with app2
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
{% block head %}
{% endblock %}
<title>{% app_title %} - {{ app_title_header }}</title>
{% include "app1/google.html" %}
</head>
app1/templates/app1/google.html
{% load app1 %}
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id={% g_tag %}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{% g_tag %}');
</script>
and now:
render takes document.html from project/templates. First it extends app_name/base.html - so it is including google.html (Google Analytics ).
And it works. But now I want to move google.html and fb.html to project templates, but theres unique G_TAG, so it has to be a tag or sth for this. I can't just move it because of {% load app1 %} in google.html.
I think it is too complicated - and I think there's easy solution - but don't have idea which way to go.
The most important limitation - I don't want to use context_processors from apps. I use context_processor only for common things, because i use the same variables in app1 and app2 and context_processor overrides it.

(Note: you may be suffering from DRY fascination ~:))
You need to hardcode the value somewhere, whether it's property in a ViewMixin, retrieve it from a shared storage or a template file - thing is, you have come to the point where you the shared functionality is as insignificant as the variable that differentiates each call: you need to output the value of a variable with some surrounding elements. That variable needs to come from somewhere, so repetition of variable = value is going to happen in one form or another.
My 2 cents...If I didn't understand the question well enough, let me know.
So if this is in your template:
<script async src="https://www.googletagmanager.com/gtag/js?id={{ g_tag }}"></script>
And this is a view mixin:
from django.views import generic
from centralapp.models import ConfigModel
class GoogleTagMixin(generic.base.ContextMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
app_config = ConfigModel.objects.get(host=self.request.get_host())
context['g_tag'] = app_config.google_tag
return context
Then you have one template and can just use the mixin in whatever view you need it to be.
If you don't want a mixin, you can do the same with Middleware and set the value on the request object.
I'm not sure what you're looking for that is "better".

Related

Django: how to set up the site name and show it at the end of all pages title

For example, there are 3 html templates with different titles:
<title>Page1</title>
<title>Page2</title>
<title>Page3</title>
How to append all the titles with the site name at the end using variable (or other ways)?:
<title>Page1 - {{Here is the configurable Site Name}}</title>
<title>Page2 - {{Here is the configurable Site Name}}</title>
<title>Page3 - {{Here is the configurable Site Name}}</title>
You normally do this by setting the site name in a base template that you then extend from your other templates.
Suppose you have this base.html template
<html>
<head>
<title>{% block page-title %}{% endblock %} - My Site</title>
</head>
...
You can then extend this template from your other pages:
{% extends "base.html" %}
{% block page-title %}My first page{% endblock %}
...
This solution is what is normally seen in many Django projects.
Now if you want to make the site name configurable, from your Django settings for example, you'll need a way to pass it along to your view for rendering. Since this is something you'll be doing for every view, it's better to do this in context processor so you don't have to do it manually.

Ajax: SyntaxError: Unexpected token < in JSON at position 2 [duplicate]

Can I use Django's template tags inside Javascript? Like using {% form.as_p %} in jQuery to dynamically add forms to the page.
Yes, I do it frequently. Your javascript has to be served through django, but if you just have it in the html header as inline javascript you'll be fine.
E.g: I use this to put prefix on a dynamic formset I use.
{% extends "base.html" %}
{% block extrahead %}
<script type="text/javascript">
$(document).ready(function() {
{# Append fields for dynamic formset to work#}
{% for fset, cap, _, tid in study_formsets.fset_cap_tid %}
$(function() {
$('.form_container_{{ tid }}').formset({
prefix: '{{ fset.prefix }}',
formCssClass: '{{ tid }}',
extraClasses: ['myrow1', 'myrow2']
});
});
{% endfor %}
});
</script>
{% endblock %}
Note in "base.html" I have a html head where the jquery libraries are loaded, that contains {% block extrahead %}{% endblock %}.
You can't use Django's template tags from your Javascript code if that's what you mean. All the Django variables and logic stop existing after the template has been rendered and the HttpResponse has been sent to the client. At that moment when Javascript executes, the client (browser) has no notion the variables you rendered the template with (such as "form").
What you can do is have Javascript modify your HTML page using chunks of HTML that were rendered by your Django template.
If you want to generate HTML on client side, I'd recommend to look at client side tempalte libraries (eg. JQuery Templates - use those with the {% verbatim %} templatetag).
If you want to use variables inside your rendered javascript I (that's my opnion), think it's a bad idea. But if all you want is to generate URL for your views, media and static files, I do this a lot.
Take a look to this github: jscssmin
Yes, you can use`
Example : `{{ user.username }}`
Be sure this is not single quotes but '(back tick / back quote)

Include css, js, html from apps in Django project, in a modular way

I have django project with several apps. In my main html template I am including the relevant resources -- js, css in this case and those entries are coded in by hand like so:
<script src="{% static 'js/test.js' %}"></script>
I'd like to modularize this so that I can somehow loop over my projects and have their dependencies included only if they are installed/enabled. In this way I can also add more apps in the future and not have to touch my main template.
Is there an elegant way to accomplish this?
My thought is that if I can pass each application's required resources to the main template as parameters via views.py then maybe I can loop over them (utilizing sekizai...):
{# Include external app resources #}
{% for app, template in installed_apps.items %}
{% include template %}
{% endfor %}
And views.py would go something like:
external_apps = [foo, bar]
external_apps = settings.EXTERNAL_APPS # Ok, this should exist in settings already
def main(request):
installed_apps = {}
for app in external_apps:
installed_apps[app] = app + "_template.html"
template = loader.get_template('main_template.html')
context = RequestContext(request, {
'installed_apps': installed_apps,
})
return HttpResponse(template.render(context))
Then for each app I would create a template that would fill out the necessary blocks in the main template file.
This approach seems pretty rigid though and I'm wondering if there is a more common or standardized way to go about this.
base.html:
...
<script src="{% static 'js/test.js' %}"></script>
{% block extra_js %}{% endblock extrajs %}
...
In your app template:
{% block extra_js %}<script src="{% static 'js/myapp.js' %}"></script>{% endblock extra_js %}

include static files from django template

I'm trying to include a static html page from a django template.
I tried using {% include the_static.html %} but this doesn't work for some unknown reason.
the_static.html page is a data page that will be modified often with an html editor.
and my_model has a url to this html and include it. But django refuses to find it although I'm sure I've setup the path correctly.
You can write your custom template tag to do this.
Create a file named includestatic.py under appname/templatetags/. Also, remember to create appname/templatetags/__init__.py, to include the app in settings and to restart the server.
includestatic.py should have this code:
from django import template
from django.contrib.staticfiles import finders
from django.utils.html import escape
register = template.Library()
#register.simple_tag
def includestatic(path, encoding='UTF-8'):
file_path = finders.find(path)
with open(file_path, "r", encoding=encoding) as f:
string = f.read()
return escape(string)
To use it in your template, put {% load includestatic %} at the top of your template, and then use the tag like {% includestatic "app/file.txt" %}.
I am not sure I understand everything yet...
You've an HTML page served by Django on a given url, let's suppose it to be http://mydjangodomain/get_the_static/. This URL is set in the urls.py of your model. Ok, that's normal.
You have a django template for this model. Let's suppose it's defined in a template directory mytemplates/mymodeltemplates/ and it's called myfrontpage.html (since in Django templates are html files).
I guess you've an URL defined in your urls.py to server that front page ? Let's suppose it's http://mydjangodomain/get_the_front_page/
Now I don't understand how your front page use your static html. Do your final front page html need the static's URL for a "src" attribute or something like it, or do you need to include the static's html into the front page's html ?
In the 1st case, you already have the URL, it's http://mydjangodomain/get_the_static/ so just use it as if.
In the 2nd case, you don't need the previous URL, get ride of it. Furthermore, put the_static.html in mytemplates/mymodeltemplates/. Then you need the {% include "/mymodeltemplates/the_static.html" %} tag. If this doesn't work, make sure you've the following in your settings:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
APPLI_ROOT_PATH = "<absolute_path_to_the_application_root_on_your_server>"
TEMPLATE_DIRS = (
'%s/mytemplates' % APPLI_ROOT_PATH,
)
Sort of resurrecting the dead, but at least with django 1.10, there's a very clean answer here:
http://www.effectivedjango.com/tutorial/static.html
an excerpt from that page:
Simple Template Inclusion We want to add the Boostrap CSS to all of
our templates, but we’d like to avoid repeating ourself: if we add it
to each template individually, when we want to make changes (for
example, to add another stylesheet) we have to make them to all the
files. To solve this, we’ll create a base template that the others
will inherit from.
Let’s create base.html in the templates directory of our contacts app.
{% load staticfiles %}
<html>
<head>
<link href="{% static 'bootstrap/css/bootstrap.min.css' %}"
rel="stylesheet" media="screen">
</head>
<body>
{% block content %}
{% endblock %}
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</body>
</html>
base.html defines the common structure for our pages, and includes a
block tag, which other templates can fill in.
We’ll update contact_list.html to extend from base.html and fill in
the content block.
{% extends "base.html" %}
{% block content %}
<h1>Contacts</h1>
<ul>
{% for contact in object_list %}
<li class="contact">{{ contact }}</li>
{% endfor %}
</ul>
add contact
{% endblock %}
Having followed this exactly, I now have a base.html that includes all my style references and the navigation bars/etc, so the html in the block content is merely the central contents of each (varying) page.
Do you mean that you want to EXTENDS the parent template the_static.html?
If yes, you should add below code at the first line of your children template:
{% extends "the_static.html" %}
Details documentation can be found here

Template Django application extending template django project

I am quite a beginner in django and I need some advices.
I am trying as much as possible to create reusable django applications that will be used in several different projects. But I don't know how to proceed with templates.
If I have an application managing user, I think the template allowing to add, remove or list a user shall be located in the application and not in the project. Templates project should define headers, footers and general organisation (correct me if I'm wrong).
However, if I want to use template inheritance I will extend project template in my application template :
{% extends "base.html" %}
{% block content %}
...
{% endblock %}
So in developping my reusable application I make the assumption that my project will have a template called base.html with a block content, and in my mind this information should not be located at application level, but in project level. In some projects I will want to display users in block content, but not necessarily in others. I could want to display user information in several places in the same page for example...
How do you developp your application template to bypass this limitation ?
Thanks in advance,
Bill
What you are describing is probably best solved with custom template tags, specifically inclusion tags.
I would do a basic html template containing a header and a footer, and many reusable templates extending the basic one, containing the different layouts I would need. I would also create reusable components (tiles, datagrids...).
For the templates :
base.html
<!doctype HTML>
<html>
<head>
....
</head>
<body>
{% block content %}
</body>
</html>
3_columns.html
{% extends "project/base.html" %}
{% block content %}
<div class="line">
<div class="column">{% block col1 %}</div>
<div class="column">{% block col2 %}</div>
<div class="column">{% block col3 %}</div>
</div>
{% endblock %}
2_lines.html
{% extends "project/base.html" %}
{% block content %}
<div class="line">{% block line1 %}</div>
<div class="line">{% block line2 %}</div>
{% endblock %}
A basic custom component :
templatetags/custom.py
import django
from django.template.defaulttags import register
#register.inclusion_tag('components/custom.html')
def custom(params):
context = {
'a': params['a'],
'b': params['b']
}
return context
templates/components/custom.html
<div class="custom">
<label>{{ a }}
<input name={{ b }}
</label>
</div>
django-admin.py collectstatic
Read docs
Files are searched by using the enabled finders. The default is to look in all locations defined in STATICFILES_DIRS and in the 'static' directory of apps specified by the INSTALLED_APPS setting.