I want to override get method in templateview:
class ...
def get(self, request, *args, **kwargs):
if request.is_ajax():
#do and return something
return super(self, Clasname).get(request, *args, **kwargs) #when not ajax
This is giving error.
Swap the arguments to super, i.e.,
return super(Clasname, self).get(request, *args, **kwargs)
Related
I am using Django Rest Framework and its class-based view, with database connection set to ATOMIC_REQUESTS=True.
To optimize the application, I would like to have it so that only PUT and POST requests are under transaction, but not GET. Since I have ATOMIC_REQUESTS on, the documentation says to use the decorator on the dispatch() method in the view. So this is what I tried:
class MyView(APIView):
def get():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def post():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def put():
print("I am in a transaction:", not transaction.get_autocommit())
return Response({})
def dispatch(self, request, *args, **kwargs):
"""Override dispatch method and selectively apply non_atomic_requests"""
if request.method.lower() == "get":
return self.non_atomic_dispatch(request, *args, **kwargs)
else:
return super().dispatch(request, *args, **kwargs)
#transaction.non_atomic_requests
def non_atomic_dispatch(self, request, *args, **kwargs):
"""Special dispatch method decorated with non_atomic_requests"""
return super().dispatch(request, *args, **kwargs)
This does not work, since the get method still reports itself as under transaction, however, if I switch the decorator to look like this:
...
#transaction.non_atomic_requests
def dispatch(self, request, *args, **kwargs):
if request.method.lower() == "get":
return self.non_atomic_dispatch(request, *args, **kwargs)
else:
return super().dispatch(request, *args, **kwargs)
def non_atomic_dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
...
This works, though obviously it's not what I want.
My questions are:
Why does the placement of the decorator matter, if I am merely returning the same thing?
How do I make this work the way I want?
I've got a UpdateView in Django that I need to restrict to only the author. I having trouble grabbing the Author off of the request.
class MyPermissionMixin(LoginRequiredMixin, UserPassesTestMixin):
def dispatch(self, request, *args, **kwargs):
user_test_result = self.get_test_func()()
if request.user != ????.user: #How do I grab the user('Author')??
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
Get Autor instance user through self.get_object()
class MyPermissionMixin(object):
def dispatch(self, request, *args, **kwargs):
if request.user != self.get_object().author:
return HttpResponseForbidden()
return super().dispatch(request, *args, **kwargs)
Is it even possible?
I can't find anything or figure it out by myself since I'm a beginner, so I turn to you guys.
Here's an example (don't worry about the use case, I just want to know if it's possible and how):
When I run this code I get that *args is not defined. What's wrong?
views.py:
class MyCreateView(CreateView):
def get(self, request, *args, **kwargs):
slug = kwargs['slug']
helper_method(self, slug)
helpers.py:
def helper_method(self, slug):
if slug == "random":
return super(self.__class__, self).get(request, *args, **kwargs)
You have to define args and kwargs, you just need to add them to your method parameters like this:
def helper_method(self, slug, *args, **kwargs):
if slug == "random":
return super(self.__class__, self).get(request, *args, **kwargs)
class MyCreateView(CreateView):
def get(self, request, *args, **kwargs):
slug = kwargs['slug']
helper_method(self, slug, *args, **kwargs)
I have a class based view, and from the get and post request I have been calling a method, to obtain information from information in the HttpResponseRedirect kwargs.
code:
class View1(View):
def get(self, request, *args, **kwargs):
... stuff ...
return render(request, self.template_name, self.context)
def post(self, request, *args, **kwargs):
... stuff ...
return HttpResponseRedirect(
reverse('results:report_experiment',
kwargs={
'sample_id': current_sample_id
}
))
class View2(CustomView):
def obtainInformation(self, kwargs):
sample_id = kwargs.get('sample_id', None)
self.sample_obj = Sample.objects.get(id=sample_id)
def dispatch(self, request, *args, **kwargs):
self.obtainInformation(kwargs)
return super(View2, self).dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
... stuff ...
return render(request, self.template_name, self.context)
def post(self, request, *args, **kwargs):
... stuff ...
return HttpResponseRedirect(
reverse('results:report_experiment',
kwargs={
'sample_id': current_sample_id
}
))
My question is, when I call self.obtainInformation(kwargs) in the dispatch method, I can access any class variables I define in BOTH the get and post methods. Previously I was calling self.obtainInformation(kwargs) in both the get and post methods of view2 (so calling the method twice).
Is this a sensible way to use the dispatch method?
Yes, overriding dispatch() as you have done looks ok, and prevents the duplication of having to call obtainInformation in get() and post().
In Django 2.2+ there is a new setup() method that you could use.
class View2(CustomView):
def setup(self, request, *args, **kwargs):
super().setup(request, *args, **kwargs)
self.obtainInformation(kwargs)
I am trying to do something like the following to work, but I keep receiving the error 'RegionsView' object has no attribute 'method'. What am I doing wrong? Thanks
#views.py
class _LanguageMixin(object):
def dispatch(self, request, *args, **kwargs):
self.langcode = kwargs.pop("langcode")
self.language = get_object_or_404(Language, pk=self.langcode)
return super(_LanguageMixin, self).dispatch(self, request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(_LanguageMixin, self).get_context_data(self, **kwargs)
context.update({"language": self.language,
"languages": Language.objects.values_list('code',
flat=True)})
return context
class RegionsView(_LanguageMixin, TemplateView):
template_name = "regions.html"
def get_context_data(self, **kwargs):
context = super(RegionsView, self).get_context_data(self, **kwargs)
regions = #......
context.update({"regions": regions})
return context
#urls.py
url(r'^(?P<langcode>[a-zA-Z-]+)/regions/$', RegionsView.as_view(), name='regions')
return super(_LanguageMixin, self).dispatch(request, *args, **kwargs)
instead of
return super(_LanguageMixin, self).dispatch(self, request, *args, **kwargs)
(request.method is used in the dispatch function, but you use self object)