I've built a menu as a templatetag in Django>1.9.
The problem is that following this solution, I can't put the templatetag at the root of the folder, as I'm getting a:
TemplateSyntaxError: 'menu' is not a registered tag library
Below is the part of my settings.py that I've modified:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# Look for base template at root of project
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
# Look for base templatetags at root of project
'libraries': {
'project_tags': 'templatetags.menu',
}
},
},
]
Even with an empty menu.py template tag like the one below I get the same error:
from django import template
register = template.Library()
#register.inclusion_tag('menu.html', takes_context=True)
def menu(context):
pass
Does Django support project-wide templatetags at all?
I've had it fixed by loading in my base.html template the module (i.e. project_tags) instead of the tag (i.e. menu), and then calling normally the tag menu:
So it's
{% load project_tags %}
...
{% menu %}
Instead of:
{% load menu %}
...
{% menu %}
Related
So far, on my entirely blank django project I have created a simple template that looks as following.
test.html:
{% block includes %}
{{ mytext }}
{% endblock includes %}
to my views.py I added the following function:
from django.template.response import TemplateResponse
def testdex(requset, template_name="test.html"):
args = {}
text = "hello world"
args['mytext'] = text
return TemplateResponse(request, template_name, args)
My settings.py includes the following:
TEMPLATE_DIR = os.path.join(BASE_DIR, "core/templates")
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [TEMPLATE_DIR],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
However, loading the template only shows me a blank page. Is there something I am missing?
I'm just learning Django and Python and want to be sure I'm doing things the right DRY way and I'm sure there's a MUCH easier way to do this...
Right now, I have the following base_template_tags.py as it's own app (added into settings.py and loaded on the HTML template {% load ... %} that allows me to access the year as an HTML tag via {% cd_year %} and/or the email address as { cd_email }. It works... but it's a hack.
Is there a better way?
from datetime import datetime
from django import template
register = template.Library()
#register.simple_tag
def current_time(format_string):
return datetime.datetime.now().strftime(format_string)
#register.simple_tag
def cd_year():
return datetime.now().year
#register.simple_tag
def cd_email():
return 'pp#pp.com'
As you guessed, there is a much more easier way built-in to django:
{% now "Y" %}
Edit
As you mentioned in the comments that you want to share a bunch of template tags among all of your apps, you can override libraries dictionary and add your custom template tags there.
Read more about that in the docs
and for your templates:
{% load your_template_tags_file_name %}
{% cd_year %}
Edit 2
This is how the TEMPLATES part of your settings.py should look like:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'libraries': { # <-----------
'global_tags': 'template_tags.global_tags',
'admin.urls': 'django.contrib.admin.templatetags.admin_urls',
},
},
},
]
and your directory structure should be like:
<your_project_dir>
├── __init__.py
├── settings.py
├── template_tags
│ ├── global_tags.py
│ ├── __init__.py
...
the global_tags.py file should contain your template tag definition and registration, as:
from datetime import datetime
from django import template
register = template.Library()
#register.simple_tag
def current_time(format_string):
return datetime.now().strftime(format_string)
#register.simple_tag
def cd_year():
return datetime.now().year
#register.simple_tag
def cd_email():
return 'pp#pp.com'
and for each template that's going to use those custom template tags:
{% load global_tags %}
{% cd_year %}
You can used below code in .html
{% block content %}
{% load staticfiles %}
{% endblock %}
Create a new folder “static” in the root of the main project.
Same level as the “templates” directory.
Add this code to your base template file (__base.html).
{% load staticfiles %}
Use this to load the files.
Add this to your settings.py file.
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
Create global context:
You have create App inside context_processor.py file
In context_processor file written:
from app.model import *
from django.contrib.auth.models import user
def employee_processor(request):
try:
emp_obj= Employees.object.filter(user=request.user)
return { ’employee’:emp_obj}
except:
user_obj=User.object.filter(id=request.user)
return { ’employee’: user_obj}
Add your context processor in your setting py file:
TEMPLATES = [{
# whatever comes before
'OPTIONS': {
'context_processors': [
# whatever comes before
"your_app.context_processors.employee_processor",
],
}
}]
Then you can used global variables in your HTML template
{{ employee }}
{{ employee.name }}
I'm starting a very simple Django app but having trouble with extending an html file.
I have base.html and index.html both within my_site/my_app/templates/my_app.
i.e.
my_site/my_app/templates/my_app/base.html and my_site/my_app/templates/my_app/index.html.
Within the index.html file I have {% extends 'base.html' %}.
My settings.py file has
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
But when I visit my index view at http://127.0.0.1:8000/index/:
def index(request):
return render(request, 'my_app/index.html')
I get the following error:
TemplateDoesNotExist at /index/
base.html
Request Method: GET
Request URL: http://127.0.0.1:8000/index/
Django Version: 1.10.3
Exception Type: TemplateDoesNotExist
Exception Value: base.html
Do I have the base.html file saved in the wrong place or is it something else? I have not been able to solve this.
It should be in my_site/my_app/templates or my_site/templates.
just getting started in Django, and I have some problems with the inheritances. It just seems that the loop for doesn't work when inheriting other template. Here's my code in base.html:
<!DOCTYPE html>
<html lang="es">
<head>
<title>{% block title %}Titulo del proyecto web{% endblock %}</title>
</head>
<body>
<div id="header">
<h1>Título del proyecto web</h1>
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
So here in the index.html the objective is to show the for loop and also the 'header' div of base. Index.html is this:
{% extends "base.html" %}
{% block title %}Questions{% endblock %}
{% block content %}
{% for pregunta in preguntas %}
<h3>{{ pregunta }} ?</h3><br/>
{% endfor %}
{% endblock %}
I've checked the code several times. If I quit the inheritance the loop works fine, but I don't know why it doesn't work when extending to base.html.
When I run the server page it just appears a blank page. Help would be highly appreciate. Thank you very much.
EDIT: Here it is my template directories structure:
Main Project/Templates/ and inside Templates folder there's the base.html and a 'preguntasyrespuestas' folder which is the app name.
And inside 'preguntasyrespuestas' folder there is the index.html template. But it automatically creates a 'base.html' also inside this folder (?) I just delete it.
And the views.py code is that shown here:
from django.http import HttpResponse,Http404
from preguntasyrespuestas.models import Pregunta
from django.shortcuts import get_object_or_404, render_to_response
def index(request):
preguntas = Pregunta.objects.all()
return render_to_response('preguntasyrespuestas/index.html',
{'preguntas': preguntas})
def pregunta_detalle(request, pregunta_id):
pregunta = get_object_or_404(Pregunta, pk=pregunta_id)
return render_to_response('preguntasyrespuestas/pregunta_detalle.html',
{'pregunta': pregunta})
Here's the settings.py template var:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ["C:/Projects/primerproyecto/Templates"],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
So, must both files (base.html and index.html) be in the Templates directory (not inside the app directory inside templates)? I've tried it and still happens the same (output a blank page), if not an error while trying to combine files locations (between theses two folders).
In your app the template folder structure must be something like:
|- preguntasyrespuestas # your app folder
|- templates
-base.html
|- preguntasyrespuestas
-index.html
-pregunta_detalle.html
....
Templates directory must be in your app folder and inside it must be another folder with the name of your app and inside this must be the template files.
EDIT
If your templates are in the app template folder you should change DIRS to an empty list: DIRS:[]
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], # change here: put an empty list
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
http://docs.djangoproject.com/en/dev/howto/static-files/
This suggests that I can use STATIC_URL in my template to get the value from settings.py.
Template looks like this:
<link href="{{STATIC_URL}}stylesheets/tabs.css" rel="stylesheet" type="text/css" media="screen" />
Settings.py looks like this:
STATIC_ROOT = ''
STATIC_URL = '/static/'
When I go to the page I just get <link href="stylesheets/tabs.css" i.e. no STATIC_URL.
What am I missing?
You have to use context_instance=RequestContext(request) in your render_to_response, for example:
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Or use the new shortcut render
As Dave pointed out, you should check if django.core.context_processors.static is in your TEMPLATE_CONTEXT_PROCESSORS variable in settings.py. As the docs said, it`s there by default.
It is not recommended to directly use the STATIC_URL variable. See the accepted answer in this question
Instead of
{{STATIC_URL}}stylesheets/tabs.css
use
{% load staticfiles %}
{% static 'stylesheets/tabs.css' %}
I have the same problem, solved like this:
in settings.py
add:
django.template.context_processors.static
here:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': TEMPLATE_DIRS,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.template.context_processors.static',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]