When I render blogpost.html page I can't see any content in my page.
My urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='Blog_home'),
path('<slug:slug>', views.blogpost, name='blogpost'),
]
my views.py
When I print blogpost function's query I got null value
from django.shortcuts import render
from django.http import HttpResponse
from blog.models import Post
# Create your views here.
def index(request):
post = Post.objects.all()
context = {'post':post}
return render(request, 'blog/bloghome.html', context)
def blogpost(request, post_id):
post = Post.objects.filter(slug=slug)
print(post)
context = {'post':post}
return render(request, 'blog/blogpost.html', context)
Template Name:- blogpost.html
{% extends 'basic.html' %}
{% block title %}Blog{% endblock title %}
{% block body %}
<div class="contaier">
<div class="row">
<div class="col-md-8 py-4">
<h2 class=" blog-post-title">{{post.title}}</h2>
</div>
</div>
</div>
{% endblock body %}
If I write like this my blogpost.html template it works.
{% extends 'basic.html' %}
{% block title %}Blog{% endblock title %}
{% block body %}
<div class="contaier">
<div class="row">
<div class="col-md-8 py-4">
<h2 class=" blog-post-title">Django</h2>
</div>
</div>
</div>
{% endblock body %}
You're passing a queryset as a context. Your post object contains a queryset of Post objects, so you can't retrieve post.title, you need either to pass only one Post object to your template, or loop through all of your objects and then display post.title for each of them.
You probably need the first option, so you need to change several things.
In your urls.py, you defined your blogpost view by blogpost(request, post_id) whereas in your urls.py you defined your url as
path('<slug:slug>', views.blogpost, name='blogpost')
If you want to get an id from your url, you should define it as
path('<int:post_id>', views.blogpost, name='blogpost')
And in your blogpost view, you do
post = Post.objects.filter(slug=slug)
but your slug isn't defined because your named it post_id.
Once again, if you want to retrieve only a post_id, you should use
post = Post.objects.get(pk=post_id)
The problem is that you are not retrieving a post with this:
post = Post.objects.filter(slug=slug)
It's a queryset, which returns zero, one, or possibly >1 objects (the latter if the slugfield isn't specified unique)
Try:
post = Post.objects.get(slug=slug)
or to better handle failure
post = get_object_or_404( Post, slug=slug)
Django template language fails quietly. If something in {{ }} fails, you get a null string substituted, not a runtime error.
Related
In my blog app I want to allow unkown users to see articles, but I also want to allow logged users to see in the same page (somewhere else) their own articles; something like:
YOUR ARTICLES: list (only if user is logged)
ALL ARTICLES: list
Note that I need to show articles based on the user logged in because the url must be this:
path('<int:user_id>/', views.IndexView.as_view(), name='index'),
index.html:
{% if user.is_authenticated %}
Your articles:
<div class="container py-5">
{% if article_list %}
{% for article in article_list %}
<div class="container">
<div class="row">
<div class="col">
{{article.author}}
</div>
<div class="col">
{{article.title}}
</div>
<div class="col">
{{article.pub_date}}
</div>
<a href=" {% url 'blog_app:detail' user_id = user.id %} ">
<div class="col">
Open article
</div>
</a>
</div>
</div>
{% endfor %}
{% else %}
<b>No articles!</b>
{% endif %}
</div>
{% endif %}
views.py:
class IndexView(ListView):
model = Article
template_name = 'blog_app/index.html'
context_object_name = 'article_list'
#return articles of a particular author
def get_queryset(self):
self.article = get_object_or_404(Article, author_id=self.kwargs['user_id'])
return Article.objects.filter(
author = self.article.author
)
My question is: How can I get from IndexView two different querysets? One with all articles and one with articles filtered by author?
Bonus question:
Can I allow unkown users to reach the articles page if the url needs to specify the user id?
After answers, this is one possible correct solution (don't focus on year and month filters, I added them but obviusly aren't related to the solution):
class IndexView(ListView):
model = Article
template_name = 'blog_app/index.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['all_article_list'] = Article.objects.all()
context['author_article_list'] = Article.objects.filter(
pub_date__year = self.kwargs['year'],
pub_date__month = self.kwargs['month'],
author = self.kwargs['user_id']
).order_by('-pub_date')
return context
In django templates I used these context names to iter articles:
Author articles:
{% if user.is_authenticated %}
{% if author_article_list %}
{% for article in author_article_list %}
...
{% endfor %}
{% endif %}
{% endif %}
All articles:
{% if all_article_list %}
{% for article in all_article_list %}
...
{% endfor %}
{% endif %}
You need to specify:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['all_articles'] = Article.objects.all()
return context
Then you can also use an if statement in th template, to check if the {{all_articles}} exists.
"Can I allow unkown users to reach the articles page if the url needs to specify the user id?"
Unauthenticated users do not have an ID, this will result in an error. If you want users to go to the author of the current article being viewed, wouldn't it be {{article.author.id}}? (Not sure if this is what you want.)
Just use a standard context. Add this metod to you view (changing names, obviously):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['book_list'] = Book.objects.all()
return context
Bonus answer:
Well, anyone can enter every instance of such view. The only thing would be to change manually number in the browser, i.e. anyone can access this link:
http://example.com/1/
But if someone is not authenticated, that link: <a href=" {% url 'blog_app:detail' user_id = user.id %} "> would raise error, but of course cause of {% if user.is_authenticated %} it's not rendered anyway.
You need to set proper permissions to your view.
I think you can also override the get_queryset() method according to different conditions, so:
class IndexView(ListView):
model = Article
template_name = 'blog_app/index.html'
context_object_name = 'article_list'
def get_queryset(self):
qs=super().get_queryset()
if self.request.user.is_authenticated:
article=get_object_or_404(Article,author_id=self.kwargs['user_id'])
return qs.filter(author=article.author) #filtered queryset
else:
return qs #default queryset
I'm trying to create a frontend data entry page for an existing model. However, when clicking the link, I get an error:
crispy_forms.exceptions.CrispyError: |as_crispy_field got passed an invalid or inexistent field
Just to be clear, adding the data from Django Admin works with no issues at all.
Having looked through a number of answered questions here, one did highlight what I believe could be problem, but it was out of context and did not provide much of an explanation.
I am trying to create a frontend entry form for users that corresponds with a foreign key.
models.py
class NewHandoff(models.Model):
handoff_pk = models.AutoField(primary_key=True)
handoff_date = models.DateField(auto_now_add=True,verbose_name="Handoff Date")
shift1_pri = models.ForeignKey(Engineer,on_delete=models.CASCADE,verbose_name="Shift 1 Primary")
shift1_sec = models.ForeignKey(Engineer,on_delete=models.CASCADE,verbose_name="Shift 1 Secondary")
def __str__(self):
return f"{self.handoff_date}"
class Meta:
verbose_name_plural = 'Handoffs'
# New Handoff Form
class NewHandoffForm(forms.ModelForm):
class Meta:
model = NewHandoff
fields = ['shift1_pri','shift1_sec']
views.py
from django.shortcuts import redirect, render
from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http.response import HttpResponse
from django.contrib import messages
from .models import AttentionForm, NewHandoffForm
# Handoff View Page
class NewHandoffView(LoginRequiredMixin,View):
def get(self, request):
greeting = {}
greeting['heading'] = "New Handoff"
greeting['pageview'] = "Handoff"
return render (request,'handoff/handoff-new.html')
def post(self, request):
if request.method == "POST":
if "add-new-handoff-button" in request.POST:
create_new_handoff_form = NewHandoffForm(request.POST)
create_new_handoff_form.save()
return redirect("/handoff/handoff-create")
handoff-new.html
{% extends 'partials/base.html' %}
{% load static %}
{% load humanize %}
{% load crispy_forms_tags %}
{% block extra_css %}
<link href="{% static 'libs/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet">
{% endblock %}
{% block contents %}
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<!-- New Form -->
<form method="POST">
{% csrf_token %}
<div class="row">
<div class="row-fluid pb-1">
<!-- Field 1 -->
<div class="mb-3">
{{ form.shift1_pri|as_crispy_field }}
</div>
<!-- End of Field 1 -->
</div>
</div>
<div class="d-flex flex-wrap gap-2">
<button type="submit" class="btn btn-primary waves-effect waves-light" name="add-new-handoff-button">Create New Handoff</button>
</div>
</form>
<!-- End of New Form -->
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_javascript %}
{% endblock %}
Someone mentioned in another post that forms should correlate with the declared form name {{ form.shift1_mod|as_crispy_field }} so it should actually be {{ create_new_handoff_form.shift1_mod|as_crispy_field }} but I have tried changing this and still get the same problem, plus, another model form works fine with just form despite the name of the form being attention_form.
Does anyone have any idea or can point me in the right direction? :)
You are not passing the form through the context in the template. As you are inheriting View, Add the following line in the get() and afterwards in the post() method appropriately:
form = NewHandoffForm()
# and then change return
return render(request,'handoff/handoff-new.html', {'form': form })
Also, you have a space after render in the get function. I hope this is a typo here, but not in your code.
I am trying to create a blog app which has posts and each posts have title, date, link and tags.
This is my models.py
# models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Meta:
ordering = ('name',)
class Post(models.Model):
title = models.CharField(max_length=300)
date = models.DateTimeField()
link = models.URLField()
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.title
#property
def tags_name(self):
return [x.name for x in self.tags]
class Meta:
ordering = ('date',)
This is my views.py
# views.py
from django.conf.urls import url, include
from django.views.generic import ListView
from blog.models import Post
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Post.objects.all().order_by("-date"), template_name="blog/blog_list.html")),
]
This is my blog_list.html
<!-- blog_list.html -->
{% extends "mysite/layout.html" %}
{% block content %}
<h1>my blog posts</h1>
<ul>
{% for post in object_list %}
<li><span class="title">{{ post.title }}</span></li>
<p>{{ post.date|date:"d-m-Y" }}</p>
{% endfor %}
</ul>
{% endblock %}
{% block sidebar %}
<h4 id="sidenav">tags</h4>
{% for post in object_list %}
<ul>
<!-- I want to show the tags here -->
</ul>
{% endfor %}
{% endblock %}
In the blog_list.html, I am showing all the post details and on the sidebar, I want to show all the tags present from all the blog posts available. Since post.tags is ManyToManyField, how can I iterate through it?
You want to use .all in the template to get all the elements in the relationship:
{% for tag in post.tags.all %}
{{ tag }}
{% endfor %}
Thanks to #hansTheFranz for correcting my bracket issue.
Regarding not repeating tags, this would be very difficult with the current context. You might want to look into instead getting the posts in your View and extracting the tags there, where you have more freedom to check for duplicates. Something like this:
def tags(request):
posts = Post.objects.all()
tag_list = []
for post in posts:
tags = post.tags.all()
for tag in tag:
if not (tag in tag_list):
tag_list.append(tag)
context_dict = { "tags": tag_list, "posts": posts }
return render(request, 'blog/blog_list.html', context_dict)
urlpatterns = [
url(r'^$', tags, name="tags"),
]
And then change your template to be more like:
{% block sidebar %}
<h4 id="sidenav">tags</h4>
<ul>
{% for tag in tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
{% endblock %}
Additionally, instead of referencing object_list you can now access the list of posts by referencing posts, because we have defined the list of posts as such in our context dictionary, which is being passed to the template.
I'm afraid I have not tested this and it may not be very efficient, but roughly speaking it should work. A lecturer at my university wrote this book: http://www.tangowithdjango.com/book17/, which encourages more of a style of writing views as I have done: separate from the URLs. If anything I've done seems unclear or contrary, you may want to have a look at the book and see if anything there makes more sense.
I am working on extending the webapp we're left off with after completing the official Django Tutorial.
One of the functionalities I am looking to add is the ability for users to add polls themselves.
I am struggling with getting the page to process the data and then redirect to the index page ('/polls').
When I submit a new poll as a logged in user, I am returned to my index page, which is supposed to show most recently published polls, or in the event of no polls, the message "No polls are available."
For some reason, I always see "No polls are available", but once I click to the index page via a link on the site, it displays all of my polls, including my most recently created one, data intact!
Any thoughts here? I think I have included the relevant info below but happy to supply more. Thanks in advance for any help/advice.
views.py
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Poll.objects.order_by('-pub_date')[:15]
#login_required
def add_poll(request):
ChoiceFormSet = formset_factory(ChoiceForm, extra=3, min_num=2, validate_min=2)
if request.method == 'POST':
form = PollForm(request.POST)
formset = ChoiceFormSet(request.POST)
if all([form.is_valid(), formset.is_valid()]):
poll = form.save()
for inline_form in formset:
if inline_form.cleaned_data:
choice = inline_form.save(commit=False)
choice.question = poll
choice.save()
return render(request, 'polls/index.html', {})
else:
form = PollForm()
formset = ChoiceFormSet()
return render(request, 'polls/add_poll.html', {'form': form, 'formset': formset})
add_poll.html
{% extends 'polls/base.html' %}
{% block title %}Add Poll{% endblock %}
{% block body_block %}
<form role="form" id="poll_form" method="post" action="{% url 'polls:add_poll' %}">
<h2 class="form-signin-heading">Add a Poll</h2>
{% csrf_token %}
<table>
{{ form }}
{{ formset }}
</table>
<br/>
<button class="btn btn-primary" type="submit" name="submit">Create Poll</button>
</form>
{% endblock %}
index.html
{% extends 'polls/base.html' %}
{% block body_block %}
{% if latest_question_list %}
<ul>
{% for poll in latest_question_list %}
<li>{{ poll.question_text }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
{% endblock %}
urls.py
from django.conf.urls import patterns, url
from . import views
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
url(r'^add_poll/$', views.add_poll, name='add_poll'),
url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
url(r'^profile_page/$', views.ProfileView.as_view(), name='profile_page'),
url(r'^edit_profile/$', views.edit_profile, name='edit_profile'),
)
When you save your form you are not redirecting.
Your are returning 'polls/index.html' with empty polls data, that's why you always get "No polls are available". But this is very incorrect, you must follow the Post/Redirect/Get (PRG) pattern, so instead of:
return render(request, 'polls/index.html', {})
do this:
return HttpResponseRedirect(reverse('polls:index'))
You don't do any redirect right now, you are just rendering your index template with an empty context (that's why you don't see anything). To redirect, you need to use HttpResponseRedirect when your form is valid.
So, please change line:
return render(request, 'polls/index.html', {})
(just over the else) to
return HttpResponseRedirect(reverse('index'))
I finally figured it out. I had to change my html form to this:
<form method="POST" action="{% url 'new_beam:beam_diagram' beam_id=1 %}" enctype="multipart/form-data">
I have a table in my MySQL database named mysite_categories, there are 4 columns but for my purposes I just need two (name, base_url).
I currently have a template '*base_categories.html*' that I use to load the categories manually.
base_categories.html (trimmed down)
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
<li>Art</li>
<li>Biography</li>
<li>Science</li>
</ul>
</div>
{% endblock %}
What I'd like to do is pull the data from the db and use it in a for loop. Something like:
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% for category in mysite_categories %}
<li>{{ category.name }}</li>
{% endfor %}
</ul>
</div>
{% endblock %}
This is probably a newbie question but is it possible to something like this without creating an app?
*EDIT 1*
These are my app files, I'll admit this is probably junk, I have tried so many edits from so many different posts I'm sure I've broke it somewhere :P. I was going to remove it and start fresh but I figure I might as well post it to see where I might have gone wrong?
views.py
from django.shortcuts import render_to_response
from categories.models import categoryList
def index(request):
categories = categoryList.objects.all()
extra_context = {"categories": categories}
return render_to_response("myapp/index.html", extra_context)
models.py
from django.db import models
class categoryList(models.Model):
#id = models.IntegerField(unique=True, db_column='ID') # Field name made lowercase.
name = models.CharField(max_length=255L, unique=True)
base_url = models.CharField(max_length=255L, unique=True)
thumb = models.CharField(max_length=1L, unique=True, blank=True)
class Meta:
db_table = 'mysite_categories'
index.html
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% for category in categories %}
<li>{{ category.title }}</li>
{% endfor %}
</ul>
</div>
As mentioned, it's probably junk at this point, if any of you can help me straighten this out it would be appreciated!
*EDIT 2*
base_right_panel.html
{% block content %}
<div style="float: right;">
<div id="base_categories" style="margin: 10px; padding-bottom: 10px;">
{% block base_categories %}
{% include "base_categories.html" %}
{% endblock %}
</div>
</div>
{% endblock %}
*Edit 3*
base_categories.html
{% block content %}
<div class="section" style="float: right;">
<h4 class="gradient">Category List</h4>
<ul>
{% if categories %}
{% for category in categories %}
<li>{{ category.title }}</li>
{% endfor %}
{% else %}
<p>no data! {{ categories|length }}</p>
{% endif %}
</ul>
</div>
{% endblock %}
*EDIT 4*
(Application name was changed to CategoryList)
CategoryList/views.py
from django.views.generic import TemplateView
from CategoryList.models import CategorylistCategorylist #<-- Changed to match inspectdb result
class IndexView(TemplateView):
template_name="categorylist.html" #<-- Changed name from index.html for clarity
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context["categories"] = CategorylistCategorylist.objects.all()
return context
CategoryList/models.py
from django.db import models
class CategorylistCategorylist(models.Model): #<-- Changed to match inspectdb
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=255L, unique=True)
base_url = models.CharField(max_length=255L, unique=True)
thumb = models.ImageField(upload_to="dummy", blank=True) #<-- Ignored inspectdb's suggestion for CharField
def __unicode__(self):
return self.name
# Re-added Meta to match inspectdb
class Meta:
db_table = 'categorylist_categorylist'
CategoryList/urls.py
from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin
from django.conf import settings
from CategoryList import views
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='categorylist'),
)
if settings.DEBUG:
urlpatterns = patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns
MySite/urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from home import views as home_view
from CategoryList import views as index_view
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', home_view.HomeView.as_view(), name="home"),
url(r'^categories/$', index_view.IndexView.as_view(), name='categorylist'),#include('CategoryList.urls')),
url(r'^admin/', include(admin.site.urls)),
#url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
)
if settings.DEBUG:
urlpatterns = patterns('',
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
url(r'', include('django.contrib.staticfiles.urls')),
) + urlpatterns
So far I can load the url "localhost:8000/categories" and I will see the list of category names appear on the right side of the screen as expected, but there is no template formatting applied. Inside my "*base_right_panel.html*" file I've tried "{% include "categorylist.html %}" to link directly to the application, which displays the correct template formatting, but displays the "{% else %}" response from "{% if categories %}" instead of the categories? I have tried changing the include to point to "categories/", which works in the browser, but it tells me it cannot find the template?
I'm sooo stumped right now..?
This answer is not meant to disagree with Alasdair's - it's just to add some more information on working with templates.
The core handler of an HTTP request to a Django application is the view. The view receives the HTTP request, as well as any arguments captured from the URL, and is responsible for returning an HttpResponse instance (or an instance of one of its subclasses) which will be returned to the browser.
The view is not bound to use any particular method to create the HttpResponse. Rendering a template to include information derived from the database and from request information or URL arguments is sufficiently common that there's code to support it, like the render shortcut or its mostly obsolete antecedent render_to_response, but this is by no means required. It's perfectly legitimate to have a view directly construct the HttpResponse:
def index(request):
return HttpResponse('This is an index page.')
Or, for very simple HTML:
def index(request):
return HttpResponse('<html><head><title>example</title></head><body>This is an index page.</body></html>')
In practice, I have often created HttpResponse instances directly to return json data or a dynamically created PDF or Excel file.
A simple way to slot information retrieved from the database into your response would be to use Python's built-in string interpolation:
def index(request):
return HttpResponse('Hello, %s' % request.user.email)
Or you could use the advanced string formatting options:
def index(request):
user_names = {}
user_names['first_name'] = request.user.first_name
user_names['last_name'] = request.user.last_name
return HttpResponse('Hello, %(first_name)s %(last_name)s' % user_names)
All this is building up to the point that it doesn't matter how you generate the text contents of your HttpResponse. All that matters is that you return one.
The template system is a powerful and extensible tool for generating text content, but that's all it does. If you look at the template docs about rendering a template, you'll see some examples that are almost exactly the same as the the string interpolation above.
render_to_response was a shortcut that would accept a template and a context and return an HttpResponse with the rendered contents of that template and context. Skipping over its context_instance and content_type parameters for the sake of demonstration, these two code blocks are identical in effect:
def index(request):
t = Template('Hello, {{ first_name }} {{ last_name }}')
c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
response_text = t.render(c)
return HttpResponse(response_text)
Assume a template index.txt exists as defined below, at the top level of an entry in the setting's TEMPLATE_DIRS tuple.
index.txt
Hello, {{ first_name}} {{ last_name}}
Then the view above could be replaced with:
def index(request):
t = get_template('index.html')
c = Context({'first_name': request.user.first_name, 'last_name': request.user.last_name})
response_text = t.render(c)
return HttpResponse(response_text)
Alternatively, you can skip the explicit creation of the context object and rendering of the template into a string thus:
def index(request):
return render_to_response('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})
On more recent versions of Django you should generally use the render shortcut rather than render_to_response - the details are a bit too much to go into if you're still struggling with getting context into your templates.
def index(request):
return render('index.html', {'first_name': request.user.first_name, 'last_name': request.user.last_name})
Of course, part of what makes templates useful is that the rendering engine can perform certain kinds of logic and lookup. I don't actually need to explictly keep looking up first_name and last_name - I can just pass in request as part of my context and look up its attributes in the templates:
index_showing_context.html
Hello, {{ request.user.first_name }} {{ request.user.last_name }}
def index_showing_context(request):
return render('index_showing_context.html', {'request': request})
Even passing in request isn't strictly necessary in that example, because one of the differences between render and render_to_response that I alluded to above is that request is always part of the context for render. But, again, that's an advanced subject.
So for your particular problem, it really doesn't matter where in your templates you render the data you want, as long as you have provided it to your view's context and are rendering the correct template. The template is in effect just a file name used to find and build a string, into which your context will be interpolated.
The {% include %} template tag is one way to mix template fragments into other templates. If I wanted to, I could set mine up like this:
header.html:
<head>
<title>This is a sample title.</title>
</head>
index.html:
<html>
{% include "header.html" %}
<body><p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p></body>
</html>
detail.html:
<html>
{% include "header.html" %}
<body><p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
<p>{{ object }}</p>
</body>
</html>
That works fine, but it's not the only option. From your question, I see that you're using blocks and template inheritance. A common idiom is to define a base template that all or almost all other templates will inherit from:
base.html
<html>
<head>
<title>{% block title %}Default title{% endblock %}</title>
{% block extra_head_elements %}{% endblock %}
</title>
<body>
{% block body_header %}Standard page header here {% endblock %}
{% block body_content %}{% endblock %}
{% block body_footer %}Standard page footer here {% endblock %}
</body>
</html>
index.html
{% extends "base.html" %}
{% block title %}index {% endblock %}
{% block body_content %}<p>This is my template body, {{ request.user.first_name }} {{ request.user.last_name }}.</p>{% endblock %}
detail.html
{% extends "base.html" %}
{% block title %}detail{% endblock %}
{% block body_content %}<p>This is a detail page, probably for something selected in the context and given the context key 'object'.</p>
<p>{{ object }}</p>
{% endblock %}
So ultimately, I am not quite sure how you should best stitch together your right panel concept because it depends on the way you want your pages to work. If it's going to be present everywhere or almost everywhere, I would recommend putting it into a base template that the rest of your templates will extend. If you want it on exactly one page, just literally include it in that template. If you want it on some but not all pages, a template fragment that you can {% include %} is probably best.
The main thing is to understand how the template engine will compose your {% include %} and {% extends %} tags, and to provide the necessary data to the template's context in your view.
Edit:
If I wanted to have a view and template pair that just retrieved the categories, this is a simple way to lay it out using your example model code and rendering. There are other options.
index.html
<html>
<head><title>Simple category listing</title></head>
<body><p>The categories are:</p>
<ul>
{% for category in categories %}
<li>{{ category.name }}</li>
{% endfor %}
</ul>
</body>
</html>
view:
def index(request):
categories = categoryList.objects.all()
extra_context = {"categories": categories}
return render_to_response("index.html", extra_context)
If I wanted to reuse the category listing on multiple pages, that gets back into the include vs. extends discussion above. Either way, the template will always require your view to pass in categories as a context variable.
You could execute custom SQL directly to fetch categories in your view, and loop through the output in your template. This would not require an app.
If you create a model, you will be able to use the Django queryset api, which is very convenient, e.g.
mysite_categories = Category.objects.all()
This does require you to create an app. However, creating an app is really easy, just use the startapp command.
python manage.py startapp myapp
Once you've created your app, you can use the inspectdb command to inspect your database, and create a model for your mysite_categories table.