That was my assumption. But there are examples like this one where:
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
context_object_name = 'post'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.object is None:
return HttpResponseRedirect(reverse('blog'))
count_visits = None
unique_views = set()
if self.request.user.is_authenticated:
post_views = PostView.objects.filter(post=self.object)
count_visits = post_views.count()
for post_view in post_views:
unique_views.add(post_view.ip)
I tried to make use of the above code, but I got an error name 'request' is not defined
. My code (below) is messed up, but I'd like to understand how I can make an explicit request
so that a form on a class-based view can work (that's for another post):
class PostDetailView(generic.DetailView):
model = Post
context_object_name = 'post'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if self.object is None:
return HttpResponseRedirect(reverse('/'))
if self.request.user.is_authenticated:
comment_form = CommentForm(request.POST)
comment_form.save()
Traceback:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/blog/2/
Django Version: 3.2.5
Python Version: 3.9.1
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog.apps.BlogConfig',
'accounts.apps.AccountsConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/detail.py", line 107, in get
context = self.get_context_data(object=self.object)
File "/Users/user/dev/assess_new/blog/views.py", line 97, in get_context_data
post = get_object_or_404(Post, pk=self.id)
Exception Type: AttributeError at /blog/2/
Exception Value: 'PostDetailView' object has no attribute 'id'
I commented out line #97 and got this (which prompted me to post the question in the first place):
name 'request' is not defined
Traceback (most recent call last):
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/Users/user/dev/assess_new/venv/lib/python3.9/site-packages/django/views/generic/detail.py", line 107, in get
context = self.get_context_data(object=self.object)
File "/Users/user/dev/assess_new/blog/views.py", line 111, in get_context_data
comment_form = CommentForm(request.POST)
Exception Type: NameError at /blog/2/
Exception Value: name 'request' is not defined
You can not return a HTTP response object in get_context_data
. Django expects that this returns a dictionary, not a HttpResponseRedirect
for example.
You can however handle to make a redirect in case that there is no such object, for example by wrapping it in a try
-except
object:
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import redirect
class PostDetailView(generic.DetailView):
model = Post
context_object_name = 'post'
def get(self, request, *args, **kwargs):
try:
self.object = self.get_object()
except ObjectDoesNotExist:
return redirect('blog')
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
count_visits = None
unique_views = set()
if self.request.user.is_authenticated:
post_views = PostView.objects.filter(post=self.object)
count_visits = post_views.count()
for post_view in post_views:
unique_views.add(post_view.ip)
context.update(count_visits=count_visits, unique_views=unique_views)
return context
In the get_context_data
method, you should return a dictionary, you can add extra items to the context
, but eventually it returns the context
. For example with the context.update(count_visits=count_visits, unique_views=unique_views)
call.