Understanting Django inheritance templates - python

Im really lost about this, im trying to understand a django inheritance template about
I have a layout with a navbar and html structure:
todos/templates/todos/layout.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
crossorigin="anonymous"
/>
<title>Practice Django</title>
</head>
<body>
<nav class="navbar navbar-dark bg-dark justify-content-between">
<div>
<a class="navbar-brand" href="/">Django app</a>
Page 1
Page 2
</div>
<form action="" class="form-inline">
<input
type="search"
placeholder="Search Todo"
aria-label="Search"
class="form-control mr-sm-2"
/>
<button type="submit" class="btn btn-outline-success my-2 my-sm-0">
Search
</button>
</form>
</nav>
<div class="container">
{% block content %} {% endblock %}
</div>
</body>
</html>
then im trying to setup a index page with a grid, a column for show todos and the another one for create a new todo.
todos/templates/todos/base.html
{% block content %}
<h1 class="text-center">Base Page</h1>
<div class="row">
<div class="col">
{% block todolist %}
{% include 'todos/todos_list.html' %}
{% endblock %}
</div>
<div class="col">
{% block addtodo %}
{% include 'todos/add_todo.html' %}
{% endblock %}
</div>
</div>
{% endblock %}
todos/templates/todos/add_todo.html
{% extends 'todos/base.html' %}
{% block addtodo %}
<h3 class="text-center">subpage addtodo</h3>
{% endblock %}
todos/templates/todos/todos_list.html
{% extends 'todos/base.html' %}
{% block todolist %}
<h3 class="text-center">subpage todolist</h3>
{% endblock %}
For try to understand it, i made a same classes for both views, todo_list and add_todo from different class sources.
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import loader
from django.views.generic import ListView, DetailView
from .models import Todo
class TodoList(ListView):
template_name = 'todos/todos_list.html'
context_object_name= 'todos'
# Lo que devuelve esta funcion se añade al context object name
def get_queryset(self):
return Todo.objects.all()
class AddTodo(ListView):
template_name = 'todos/add_todo.html'
context_object_name= 'todos'
# Lo que devuelve esta funcion se añade al context object name
def get_queryset(self):
return Todo.objects.all()
My urls.py i guess, to show both classes in index pages, the same route url
from django.urls import path
from . import views
urlpatterns = [
path('', views.TodoList.as_view(), name='todolist'),
path('', views.AddTodo.as_view(), name='addtodo')
]
But this does not work, with this error:
RecursionError at /
maximum recursion depth exceeded while calling a Python object
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 3.1.1
Exception Type: RecursionError
Exception Value:
maximum recursion depth exceeded while calling a Python object
Exception Location: /home/adrian/.local/lib/python3.8/site-packages/django/utils/functional.py, line 241, in inner
Python Executable: /usr/bin/python3
Python Version: 3.8.2
Python Path:
['/home/adrian/code/python/practice',
'/usr/lib/python38.zip',
'/usr/lib/python3.8',
'/usr/lib/python3.8/lib-dynload',
'/home/adrian/.local/lib/python3.8/site-packages',
'/usr/local/lib/python3.8/dist-packages',
'/usr/lib/python3/dist-packages']
Server time: Thu, 24 Sep 2020 16:43:24 +0000
I was thinking to make both operations (show todo list and add a new todo form) with the same class, but i dont know how do it that properly, the object its show a both classes, templates in the same route, in this case in root /.
Any clues about? thanks in advance

You should not use {% include %}, since then you end up with infinite recursion. You can for example make a base:
{% block content %}
<h1 class="text-center">Base Page</h1>
<div class="row">
<div class="col">
{% block items %}
{% endblock %}
</div>
<div class="col">
{% block otheritems %}
{% endblock %}
</div>
</div>
{% endblock %}
If you later use {% extend … %} [Django-doc], it means you take the entire template of the one your refer to, but for the blocks you specify and the "child template", you render another value. So your child can look for example as:
{% extends 'todos/base.html' %}
{% block items %}
<h3 class="text-center">subpage addtodo</h3>
{% endblock %}
{% extends 'todos/base.html' %}
{% block items %}
<h3 class="text-center">subpage todolist</h3>
{% endblock %}
Here you will thus render the <h1 class=""> part in the child templates. The only thing that will differ is that the part in the block {% block items %} … {% endblock %} by the content you provide.
Here it however looks like you want two views to provide content for the same page. That is not how it works. A view is the logic that maps a request to a response. A view does not per se renders a template, nor does it only renders maximum one template. A view can render as much templates as you want.
If you thus want a single page with two items to fill in, you make a view, that renders for example a template that fills in the two blocks. So we thus define a single URL pattern for this path:
from django.urls import path
from . import views
urlpatterns = [
path('', views.TodoList.as_view(), name='add_todo'),
]
and in the view, we allow one to also access the list of todos:
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.template import loader
from django.views.generic import ListView, DetailView
from .models import Todo
class TodoList(CreateVieww):
template_name = 'todos/todos_list.html'
model = Todo
fields = '__all__'
def todos(self):
return Todo.objects.all()
in the template, we finally fill in two blocks: one with the Todos, and one with the form:
{% extends 'todos/base.html' %}
{% block items %}
{% for todo in view.todos %}
{{ todo }}
{% endfor %}
{% endblock %}
{% block otheritems %}
<form method="post" action="{% url 'add_todo' %}">
{{ form }}
</form>
{% endblock %}

Related

Django variable doesn't get passed to template

Basically, what happens here, the list user_data doesn't get passed to the template, I can't figure out why. Does anyone have any ideas please? When I use the search bar I just get the else condition from the template, and it never shows any variable. I also tried to create different variables to pass to the template, but none of them got passed for some reason.
This is in my views.py:
#login_required(login_url='login_user')
def profiles(request):
context = {}
if request.method == "POST":
data = request.POST.get('search_input')
if len(data) > 0:
username_result = NewUser.objects.filter(username__icontains=data).distinct()
email_result = NewUser.objects.filter(email__icontains=data).distinct()
user_data = []
for account in username_result:
user_data.append((account, False))
context['usernames'] = user_data
return render(request, "profiles/search_user.html", context)
else:
return render(request, "profiles/profiles.html")
return render(request, "profiles/profiles.html")
Then my template looks like this:
{% extends 'profiles/base.html' %}
{% block title %}One For All{% endblock %}
{% load static %}
<!-- importing css file -->
{% block style %}<link rel="stylesheet" type="text/css" href="{% static 'css/search_user.css'
%}">{% endblock %}
{% block content %}
<!-- navigation bar -->
<div class="navBar">
<!-- logo and logo spacers -->
<div class="logo_spacer"></div>
<div class="logo"></div>
<!-- Sign Up Button -->
<a class="homeBtn" href="{% url 'profiles' %}">Home</a>
{% if is_self %}
<a class="settingsBtn" href="{% url 'settings' user=user.username %}">Profile Settings</a>
{% else %}
<a class="settingsBtn" href="{% url 'user_profile' username=user.username %}">My Profile</a>
{% endif %}
<p>Top Menu</p>
</div>
<!-- main body of login page -->
<div class="main">
{% if user_data %}
<p>We find users</p>
{% for account in user_data %}
<div>
<a class="profile-link" href="{% url 'user_profile' username=user.0.username %}">
<!--<img class="img-fluid profile-image" src="{{account.0.avatar.url}}" alt="">--></a>
</div>
{% endfor %}
{% else %}
<p>This is when user_data doesn't exist or doesn't get passed to template: {{ user_data }} </p>
{{ user_data }}
{% endif %}
</div>
<div class="bottom">
<p>Bottom</p>
</div>
{% endblock %}
{% block js_block %}
{% endblock %}
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('logout/', views.logoutUser, name='logout'),
path('post/', views.post, name='post'),
path('', views.profiles, name='profiles'),
path('search_user/', views.profiles, name='profiles'),
path('UserProfile/<str:username>/', views.user_profile, name='user_profile'),
path('Settings/<str:user>/', views.settings, name='settings'),
]
In the view you set:
context['usernames'] = user_data
But in the template you reference:
{% if user_data %}
<p>We find users</p>
{% for account in user_data %}
user_data doesn't exist in the context - you need to reference usernames instead, or change the view to call it user_data

Problem in calling items from the database django

I am trying to create a music streaming website.I have created a base template and extended it to two other templates.One is song_list.html and musicplayer.html.
I have coded the views and urls to get absolute url.
my song_list.html:
{% extends "home.html" %}
{% block content %}
<div class="container">
{% for post in posts %}
{{post.song_title}} by {{post.artist}} from {{post.album}}<br>
{% endfor %}
</div>
<div class="container">
{% include "pagination.html" with page=page_obj %}
</div>
{% endblock %}
I want to render songs from the database in the musicplayer page after clicking the anchor tag.
my msicplayer.html:
{% extends "home.html" %}
{% load i18n %}
{% block content %}
<div class="container">
<form class="" action="mediaplayer.html" method="get">
<div class="data-content">
<div class="container">
<div id="img-1" class="tabcontent">
<div class="blog-content">
<div class="row">
<div class="col-sm">
<div class="card" style="width: 18rem;">
<div class="img">
<img class="img-thumbnail" src="{{ post.img.url }}" alt="">
</div>
<div class="card-body">
<div class="title">
<p>{% trans 'Artist:' %} {{post.artist}} </p><br>
<p>{% trans 'Title:' %} {{post.song_title}}</p><br>
<p>{% trans 'Album:' %} {{post.album}}</p><br>
<p>{% trans 'Duration' %} {{post.song_duration}}</p><br>
</div>
<audio controls>
<source src='{{ post.song.url }}' type="audio/mpeg">
Your browser does not support the audio element.
</audio>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
My app views:
from django.shortcuts import render,get_object_or_404
from .models import song_thumb
from django.core.paginator import Paginator, EmptyPage,PageNotAnInteger
from django.views.generic import ListView
# Create your views here.
class SongListView(ListView):
model=song_thumb
context_object_name='posts'
paginate_by=20
template_name='songlist.html'
def song_detail(request, year, month, day, post):
post=song_thumb.objects.all()
return render(request,'musicplayer.html',{'post': post})
my app models:
from django.db import models
from django.utils import timezone
from django.urls import reverse
# Create your models here.
class song_thumb(models.Model):
artist=models.CharField(max_length=100,null=True)
uploaded_by=models.CharField(max_length=100,null=True)
song_title=models.CharField(max_length=100,null=True)
slug=models.SlugField(max_length=250,null=True)
album=models.CharField(max_length=100,null=True)
song_duration=models.FloatField(null=True)
img=models.ImageField(upload_to='pics',null=True)
song=models.FileField(upload_to='media',null=True)
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse('song_detail',args=[self.publish.year,
self.publish.month,
self.publish.day, self.slug])
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.song_title
my app urls:
urlpatterns = [
path('',views.SongListView.as_view(),name='songs'),
path('<int:year>/<int:month>/<int:day>/<slug:post>/',views.song_detail,
name='song_detail'),
Like i said,I want a new page with the songdetails and mediaplayer to be rendered after i click the anchor tag in songlist.html.But when I click it i get a blank page.
here, you need to get the post as per the id but you are rendering everything here in you detail. So you can do this
view.py
from django.shortcuts import get_object_or_404
def song_detail(request, post_id):
post=get_object_or_404(Course, pk=post_id)
return render(request,'musicplayer.html',{'post': post})
urls.py
path('<int:post_id>/',views.song_detail,
name='song_detail'),
in you acnhor tag you can link to the particular post
<a href="{% url 'song_detail' post.id %}">

Template not rendering properly with if user.is_authenticated for Django

I'm trying to incorporate an template tag/inclusion tag into my sidebar for the site. The main section of the page updates properly when I put:
{% if user.is_authenticated %}
<h1> Hello {{ user.username }}
{% else %}
<h1> Hello </h1>
{% endif %}
When I try to use the same principle in my template tag/sidebar, it seems to ignore user.is_authenticated and will always show 'login' and 'register', when it should be just showing 'logout'.
The body of the html (main index page):
{% load Kappa_extras %}
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-2" id="side_section">
{% block sidebar %}
{% get_game_list %}
{% endblock %}
</div>
<!--Main section-->
<div class="col-sm-10" id="main_section">
{% block body %}
{% endblock %}
</div>
</div>
</div>
The get_game_list function from 'Kappa_extras':
from django import template
from Kappa.models import Game, Game_Page
from django.contrib.auth.models import User
register = template.Library()
#register.inclusion_tag('Kappa/sidebar.html')
def get_game_list():
return {'game_list': Game.objects.all()}
and the 'Kappa/sidebar.html':
<div id="side_default_list">
<ul class="nav">
<li>Kappa</li>
{% if user.is_authenticated %}
<li>Log Out</li>
{% else %}
<li>Log In</li>
<li>Register</li>
{% endif %}
</div>
I checked a few older inquires though none of them are working properly. I tried putting request into def get_game_list(request): but it just said did not receive value for the argument. How do I get the sidebar to update properly when user.is_authenticated?
You need to pass the user to your inclusion tag.
#register.inclusion_tag('Kappa/sidebar.html')
def get_game_list(user):
return {'game_list': Game.objects.all(), 'user': user}
Then in your template, call the tag with
{% get_game_list user %}
Alternatively, you can set takes_context=True in your inclusion tag, so that you can access the user from the template context.
#register.inclusion_tag('Kappa/sidebar.html', takes_context=True)
def get_game_list(context):
return {'game_list': Game.objects.all(), 'user': context['user']}
In this case, you don't need to pass the user to the template tag any more.
{% get_game_list %}
See the docs for more information and other examples.

Transferring my website from PHP to Django

I'm transferring my website from PHP to Django, and now I have to make a sidebar.
I want the entries to come from the DB, and than I want them to become hyperlinks for other pages..
How can I do that?
nav.html
<nav class="menu" id="theMenu">
<div class="menu-wrap" data-spy="scroll">
<h1 class="logo">MY BOOKS</h1>
<i class="icon-remove menu-close"></i>
{% for question in latest_question_list %}
{{ question.naslov }}
{% endfor %}
</div>
<div id="menuToggle"><i class="icon-reorder"></i></div>
</nav>
master2.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="/static/font.min.css" rel="stylesheet">
<link href="/static/bootstrap.min.css" rel="stylesheet">
<link href="/static/font-awesome.min.css "rel="stylesheet">
<link href="/static/main.css" rel="stylesheet">
</head>
<body data-spy="scroll" data-offset="0" data-target="#theMenu">
{% include "nav.html" %}
{% include "header2.html" %}
{% block h1 %}{% endblock %}
<script src="/static/jquery.js"></script>
<script src="/static/bootstrap.min.js"></script>
<script src="/static/jquery.isotope.min.js"></script>
<script src="/static/jquery.prettyPhoto.js"></script>
<script src="/static/main2.js"></script>
</body>
</html>
views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.all()
context = {'latest_question_list': latest_question_list}
return render(request, 'papers/index.html', context)
def detail(request, slug):
question = Question.objects.get(slug=slug)
return render(request, 'papers/detail.html', {'question': question})
urls.py
from django.conf.urls import include, url
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.contrib import admin
urlpatterns = [
url(r'^$', 'papers.views.index', name='index'),
url(r'^admin/', include(admin.site.urls)),
url(r'^(?P<slug>[\w_-]+)/$', 'papers.views.detail', name='detail'),
]
urlpatterns += staticfiles_urlpatterns()
detail.html
{% extends "master2.html" %}
{% block h1 %}
<div id="g">
<div class="container">
<div class="row">
<h3>{{ question.naslov }}</h3>
<br>
<br>
<div class="col-lg-6 desc "><p>{{ question.opsirnije_text }}</p></div>
<div class="col-lg-4 desc desc-b">
<p>{{ question.opsirnije_text }}</p>
</div>
</div>
</div>
</div>
{% endblock %}
{% block title %} Detail {% endblock %}
You might be looking for the for template tag.
{% for question in latest_question_list %}
{{ question.naslov }}
{% endfor %}
Now, if you want the list of questions to show up on all (or almost all) pages, you could write a template context processor that adds them to all contexts.

Django doesn't seem to detect my login.html, block problem?

I'm creating a web app with django 1.2.4.
I am using contrib.auth.views.login, I have followed every step but it seems I have forgotten something cause I don't see the login form. Here is my folder structure:
/templates/
base.html
/myapp/
object_list.html
...
/registration/
login.html
...and here is my login.html:
{% extends "base.html" %}
{% block mylogin %}
<div class="horizontal">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
<div class="login_box">
<div class="login_text">{{ form.username.label_tag }}</div><div class="login_input">{{ form.username }}</div>
<div class="password_text">{{ form.password.label_tag }}</div><div class="password_input">{{ form.password }}</div>
<input id="button_login" type="submit" value="" />
</div>
</form>
</div>
{% endblock %}
...and in my base.html I have:
<div id="some_div">
{% block mylogin %} {% endblock %}
</div>
I have a basestyle.css included in base.html and the other templates inherit correctly too... it seems to be a block problem...
Any solution??
Thnak you
Instead of inserting of a block I used the include tag in base.html, just like this:
{% include "registration/login.html" %}
If you’d prefer not to call default (django provided) template registration/login.html, you can pass the template_name parameter via the extra arguments to the view in your URLconf.
For example, this URLconf line would use myapp/login.html instead:
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),
Reference : Django official documentation
It solves my problem. Hope this works for others.

Categories