I am new with Django and trying to understand how to use templates and I have an issue with template extending. I have 3 templates. the first one in the base.html
{% load staticfiles%}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" type="text/css" href="{%static 'css/main.css'%}">
<title>Home</title>
</head>
<body >
<div class="page-header">
<h1>Django Project</h1>
</div>
<div class="content container">
<div class="row">
<div class="col-sm-8">
{%block content %}
{%endblock%}
</div>
<div class="col-sm-4">
{%block lastposts %}
{%endblock%}
</div>
</div>
</div>
</body>
</html>
Second one is post_list.html (which I render from views)
{% extends 'blog/base.html' %}
{% block content %}
{%for post in posts %}
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaks}}</p>
<p><b>Author: </b>{{post.author}}</p>
<p><b>Published Date: </b>{{post.published_date}}</p>
{%endfor%}
{% endblock %}
and latest_posts.html
{% extends 'blog/base.html' %}
{% block lastposts %}
<h3>Latest Posts</h3>
{%for post in posts%}
<h4>{{post.title}}</h4>
{% endfor %}
{% endblock %}
The problem is that the content of latest_posts.html does not show up. I know that something is wrong. In that case how I can use extending in django to to separate my code in these 3 files. Thanks.
*UPDATE
views.py
from django.shortcuts import render
from django.utils import timezone
from .models import Post
# Create your views here.
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
]
If you want to display the contents of latest_posts.html in post_list.html, you'll have to include it
post_list.html
{% extends 'blog/base.html' %}
{% block content %}
{%for post in posts %}
<h1>{{post.title}}</h1>
<p>{{post.text|linebreaks}}</p>
<p><b>Author: </b>{{post.author}}</p>
<p><b>Published Date: </b>{{post.published_date}}</p>
{%endfor%}
{% endblock %}
{%block lastposts %}
{% include 'blog/latest_posts.html' %}
{% endblock %}
latest_posts.html (only remove the extend and block tags)
<h3>Latest Posts</h3>
{%for post in posts%}
<h4>{{post.title}}</h4>
{% endfor %}
Related
I am trying to use Django's class based authentication views and am getting the following error when attempting to access the login view:
NoReverseMatch at /account/login/
Reverse for 'register' not found. 'register' is not a valid view function or pattern name.
Error during template rendering
In template /Users/justin/Desktop/Programming/Python/django_book/social/website/account/templates/base.html, error at line 0
All authentication templates are stored at account/templates/registration/ and dashboard.html is stored at account/templates/account/, here is the code:
account/urls.py:
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
urlpatterns = [
path('', views.dashboard, name = 'dashboard'),
path('login/', auth_views.LoginView.as_view(), name = 'login'),
path('logout/', auth_views.LogoutView.as_view(), name = 'logout'),
]
login.html:
{% extends "base.html" %}
{% block title %}Log-in{% endblock %}
{% block content %}
<h1>Log-in</h1>
{% if form.errors %}
<p>
Your username and password didn't match.
Please try again.
</p>
{% else %}
<p>Please, use the following form to log-in. If you don't have an account register here</p>
{% endif %}
<div class="login-form">
<form action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}" />
<p><input type="submit" value="Log-in"></p>
</form>
</div>
{% endblock %}
base.html:
{% load static %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title%}{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/base.css' %}">
</head>
<body>
<div id="header">
<span class = 'logo'>Bookmarks</span>
{% if request.user.is_authenticated %}
<ul class = 'menu'>
<li {% if section == "dashboard" %}class="selected"{% endif %}>
My dashboard
</li>
<li {% if section == "images" %}class="selected"{% endif %}>
Images
</li>
<li {% if section == "people" %}class="selected"{% endif %}>
People
</li>
</ul>
{% endif %}
<span class = 'user'>
{% if request.user.is_authenticated %}
Hello {{ request.user.first_name }},
Logout
{% else %}
Login
{% endif %}
</span>
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
Note sure if this is needed but the account/views.py with the dashboard view:
from django.contrib.auth.decorators import login_required
#login_required
def dashboard(request):
return render(request,
'account/dashboard.html',
{'section': 'dashboard'})
and dashboard.html:
{% extends "base.html" %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h1>Dashboard</h1>
<p>Welcome to your dashboard.</p>
{% endblock %}
I am following the book 'Django 2 By Example' and at this point I believe I have directly copy and pasted the code from here (https://github.com/PacktPublishing/Django-2-by-Example/tree/master/Chapter04) to try and fix this error, but I am still getting. I should note that I am using Django 3.2.6 and am not sure if this is causing it. Thanks for any help with this.
I have the following three files in a Django App, with the template engine being Jinja2
skeleton.html
<head>
{% block head_content %}
<meta charset="utf-8">
<title> {% if page_title %} {{ page_title }} | {% endif %} Bhargavi Books & Stationery </title>
<link rel="stylesheet" href="{{ static("css/semantic.min.css") }}">
<link rel="stylesheet" href="{{ static("Icons/font-awesome.min.css") }}">
{% endblock head_content %}
</head>
<body>
<div id="navigation">
{% block navigation %}
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
{% endblock navigation %}
</div>
<div id="frame">
{% block frame_content %}
<p> Body content goes here. Body for {{ content_name }}</p>
{% endblock frame_content %}
</div>
<div id="app">
{% block app_content %}
<p> APP content goes here. Body for {{ content_name }}</p>
{% endblock app_content %}
</div>
{% block scripts %}
<script src="{{ static("js/jquery.js") }}"></script>
<script src=" {{ static("js/semantic.min.js") }} "></script>
{% endblock scripts %}
</body>
base.html
{% extends "skeleton.html" %}
{% from "macros/globalmacros.html" import
SUIIconList,SUISimpleList,
SUIImageLabel,SUILabel,
SUIActionInput,SUILabeledInput,SUIInput,
SUIDimmableActionCard,SUICard,
%}
{% block frame_content %}
Frame Content
{% endblock frame_content %}
{% block scripts %}
{{ super() }}
<script src=" {{ static("js/globalmacros.js") }} "></script>
{% endblock scripts %}
dashboard.html
{% extends "base.html" %}
<div>
{% block body_content %}
Body 3
{% endblock body_content %}
</div>
<div>
{% block app_content %}
DASHBOARD
{% endblock app_content %}
</div>
In this setup, Jinja renders everything except the "DASHBOARD" in the final page. However, when I add an empty block in "base.html", like so..
{% block app_content %}
App content Goes here...
{% endblock app_content %}
In the final template, "DASHBOARD" is printed. Is this some quirk in Jinja? Is this behavior defined in any docs??
I understand your issue: you've got template A, template B (extends template A), and template C (extends template B). There's a block defined in template A, but it's not showing up in the page that uses template C, unless you define that block in template B. If you do that, then the block in question shows up.
First: you are correct in your understanding that this is not how the Jinja template hierarchy is supposed to work. Second, I did not encounter your issue (found a different one, though), and I have constructed a proof to demonstrate this. Here's what I did (again, using Python 3 and Django 1.11):
$ python startproject myapp
In the myapp/myapp/settings.py file, I updated the template engine:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [
os.path.join(BASE_DIR, 'myapp/templates') # hack / should add `myapp` to INSTALLED_APPS instead
],
'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',
],
},
},
]
In myapp/myapp/urls.py, I created a dummy view function & route:
from django.conf.urls import url
from django.shortcuts import render_to_response
def home(request):
return render_to_response('dashboard.html')
urlpatterns = [
url(r'^$', home),
]
And finally, I established those templates, but I removed the call to import your macros, along with all instances of static().
Here is the myapp/myapp/templates/skeleton.html file:
<!doctype html>
<html lang="en">
<head>
{% block head_content %}
<meta charset="utf-8">
<title> {% if page_title %} {{ page_title }} | {% endif %} Bhargavi Books & Stationery </title>
{% endblock head_content %}
</head>
<body>
<div id="navigation">
{% block navigation %}
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
{% endblock navigation %}
</div>
<div id="frame">
{% block frame_content %}
<p> Body content goes here. Body for {{ content_name }}</p>
{% endblock frame_content %}
</div>
<div id="app">
{% block app_content %}
<p> APP content goes here. Body for {{ content_name }}</p>
{% endblock app_content %}
</div>
{% block scripts %}
{% endblock scripts %}
</body>
</html>
Here is the myapp/myapp/base.html file:
{% extends "skeleton.html" %}
{% block frame_content %}
Frame Content
{% endblock frame_content %}
{% block scripts %}
{{ super() }}
{% endblock scripts %}
And here is the myapp/myapp/templates/dashboard.html file:
{% extends "base.html" %}
<div>
{% block body_content %}
Body 3
{% endblock body_content %}
</div>
<div>
{% block app_content %}
DASHBOARD
{% endblock app_content %}
</div>
And here is the output, after viewing that page in my browser:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Bhargavi Books & Stationery </title>
</head>
<body>
<div id="navigation">
<div class="ui three item menu">
<a class="active item">Home</a>
<a class="item">New Bill</a>
<a class="item">View Bills</a>
</div>
</div>
<div id="frame">
Frame Content
</div>
<div id="app">
DASHBOARD
</div>
</body>
</html>
Since this all works as expected*, my conclusion is that you might have a problem with the base.html template file. Perhaps it's failing to import your macros, and subsequently not behaving correctly? I notice a trailing comma in there, and I'm not sure if that could be problematic or not. I would suggest using the above code as a starting point, and then slowly add back in the parts that I stripped out, and perhaps the problem will become visible/understandable.
*One thing I found odd, that I don't understand: the body_content block is completely missing from my output, unless I define that block in the skeleton.html template. It doesn't work if I define it in the base.html template, which seems wrong to me, because then we're not really extending that second template (base.html)... so there does seem to be something weird there... but I was not able to encounter the original issue you described, so maybe this will be helpful in that particular regards, at least.
I created a "base.html" template to hold my nav bar and other elements that are recurrent on my website.
When I extend this template and put values into my blocks one of them doesn't want to work properly.
In my code I try to set the class value of my nav element to "active" depending on which page I'm in (it might not be the best solution). This block never works.
Thank you for your help :)
urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^addProduct/$', views.addProduct, name='addProduct'),
]
views.py
def index(request):
latest_product_list = Product.objects.all().order_by('-id')[:5]
return render(request, 'main/index.html', {'latest_product_list': latest_product_list})
def addProduct(request):
# Do things
return render(request, 'main/add_product.html', {'form':form})
base.html
<!DOCTYPE html>
<html lang="fr">
<head>
#header informations
</head>
<body>
<div class="container-fluid">
<div class="row">
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
</div>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="{% block navbar_class-index %}{% endblock %}">Index</span></li>
<li role="presentation" class="{% block navbar_class-addProduct %}{% endblock %}">Ajouter un produit</li>
</ul>
<div class="row" id="content">
{% block content %}{% endblock content %}
</div>
</div>
</body>
index.html
{% extends "base.html" %}
{% block navbar_class-index %}active{% endblock %}
{% block content %}
<div class="col-md-12">
## Here is my content
</div>
{% endblock content %}
add_product.html
{% extends "base.html" %}
{% block navbar_class-addProduct %}active{% endblock %}
{% block content %}
<div class="col-md-12">
<form action="{% url 'main:addProduct' %}" method="post">
{% csrf_token %}
<label> Entrez votre produit et cliquez sur Add Product.</label><br/><br/>
<label> Produit : </label>{{form.form_product_url}}
<input type="submit" value="Add Product" />
</form>
</div>
{% endblock content %}
I guess your base.html file is not in the correct folder !
I realise I'm doing something basic wrong here, just not sure what it is. I'm not getting any errors, but I'm not getting any of the model data displayed when I load the page.
Here's what I'm trying to do:
Apps: base, blog, resume
I'm trying to get the models from blog and resume to show up in the view of base. Both the blog and resume apps work fine on their own.
base/views.py
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from testpro.blog.models import Post
from testpro.resume.models import Project
def main(request):
"""Main listing."""
posts = Post.objects.all().order_by("-created")
projects = Project.objects.all().order_by("-created")
return render_to_response("list.html", dict(posts=posts, projects=projects, user=request.user))
list.html template
{% extends "bbase.html" %}
{% block content %}
<div class="main">
<h3>Blog Posts</h3>
<!-- Posts -->
<ul>
{% for post in posts.object_list %}
<div class="title">{{ post.title }}</div>
<ul>
<div class="time">{{ post.created }}</div>
<div class="body">{{ post.body|linebreaks }}</div>
</ul>
{% endfor %}
</ul>
<!-- Projects -->
<h3>Projects</h3>
<ul>
{% for project in projects.object_list %}
<div class="title">{{ project.title }}</div>
<ul>
<div class="industry">{{ project.industry }}</div>
<div class="time">{{ project.created }}</div>
<div class="body">{{ project.body|linebreaks }}</div>
</ul>
{% endfor %}
</ul>
</div>
{% endblock %}
finally, urls.py
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^main/', 'base.views.main'),
(r'^admin/', include(admin.site.urls)),
)
What stupid mistake am I making? The template renders, it just doesn't contain any model data.
Edit: Added bbase.html template
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <title>{% block title %}Test Project{% endblock %}</title> </head>
<body>
<div id="sidebar"> {% block sidebar %} {% endblock %} </div>
<div id="container">
<div id="menu">
{% block nav-global %}
<!-- MENU -->
<h3>MyBlog</h3>
{% if user.is_staff %}
Admin
Add post
{% endif %}
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</div>
</body>
</html>
{% for project in projects.object_list %}
# should be
{% for project in projects %}
and
{% for post in posts.object_list %}
# should be
{% for post in posts %}
QuerySets don't have an object_list attribute I'm aware of, so the template engine is silently failing on it.
I'd like to deliver special versions of my django site for different (mobile-)browser.
What are possible solutions to do this?
In your view, do smthg like this
def map(request, options=None, longitude=None, latitude = None):
if 'iPhone' in request.META["HTTP_USER_AGENT"]:
user_agent = 'iPhone'
elif 'MSIE' in request.META["HTTP_USER_AGENT"]:
user_agent ='MSIE'
else: user_agent=''
print user_agent
return render_to_response('map/map.html',
{
'user_agent': user_agent
})
and in your template
{% ifnotequal user_agent "iPhone" %}
{% ifequal user_agent "MSIE" %}
{% include 'map/map_ie.html' %}
{% else %}
{% include 'map/map_default.html' %}
{% endifequal %}
{% else %}
{% include 'map/map_iphone.html' %}
{% endifnotequal %}
best practice: use minidetector to add the extra info to the request, then use django's built in request context to pass it to your templates like so.
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
then in your template you are able to introduce stuff like:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>