Stack Overflow Asked by Pax on December 11, 2021
The question is also inspired from documentation here.
I am using generic view (ListView) in Django in order to list out all the questions, current logged in user has asked. I was curious to do it without creating a View in views.py
. So in urls.py I added a path like:
urlpatterns += [
path('myqn/', login_required(views.ListView.as_view(model=models.Question, queryset=models.Question.objects.filter(user__id=request.user.id), template_name='testapp/question_list.html', context_object_name='questions')), name='myqn'),
]
Its giving me that:
NameError: name ‘request’ is not defined
I know it. Since, request object is passed by the URLConf to the View class/function. So, is there a way, I can access the user.id in this scope.
PS: The code works if I replace user__id=9
. It lists out all the questions asked by user-9. 🙂
No, You can't.
The as_view()
accepts any class attributes of a view class. In your case, the request
object will not accessible from the class
class Foo(ListView):
queryset = Question.objects.filter(user__id=request.user.id)
The above snippet you can't reference the request
and hence also in your urls.py
In these kinds of complex situations, we should override the get_queryset()
, as you know.
Answered by JPG on December 11, 2021
You normally do this by overriding the get_queryset
method in a subclass of the ListView
. So you can create a view:
# app/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.list import ListView
from app.models import Question
class QuestionListView(LoginRequiredMixin, ListView):
model = Question
template_name='testapp/question_list.html'
context_object_name='questions'
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
user_id=self.request.user.id
)
In the urls.py
you then use the QuestionListView
# app/urls.py
from django.urls import path
from app.views import QuestionListView
urlpatterns += [
path('myqn/', QuestionListView.as_view(), name='myqn'),
]
You can define a function or lambda expression with:
import inspect
def custom_queryset(*args, **kwargs):
self = inspect.currentframe().f_back.f_locals['self']
return Question.objects.filter(
user_id=self.request.user.id
)
urlpatterns += [
path('myqn/', QuestionListView.as_view(get_queryset=custom_queryset), name='myqn'),
]
This is however not a good idea. First of all, it inspects the call stack, and if later the ListView
is altered, it might not work anymore. Furthermore here this listview will not check if the user has logged in for example. We can not make use of the method resolution order (MRO) to make a call to a super()
method.
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin
mixin [Django-doc].
Answered by Willem Van Onsem on December 11, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP