Django DRY need - django

I call the "dispatch" method in all of my CRUD classes.
How can I put it somewhere else to avoid repetition? ideally in an external file
Thanks a lot
class PublicationsListView(LoginRequiredMixin, TemplateView):
template_name = 'pages/publications/index.html'
def dispatch(self, request, *args, **kwargs):
if (self.request.user.groups.filter(Q (name='proprietaire') | Q (name='super-administrateur')).exists()) and 'flotte_id' not in self.request.session :
messages.warning(self.request, mark_safe("Veuiller choisir ..."))
return redirect('dashboards:home')
else :
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
....
i tried de put the method elsewhere , but each time : "self" or "request" undefined

Related

How to get the self variable inside the etag_func and last_modified_func functions Django

I am using the django http condition to set the last_modified and e_tag headers.
Here is my set up:
def my_last_modified(request, *args, **kwargs):
return None
def get_etag_key(request, *args, **kwargs):
return None
class ProductsListAPIView(ListAPIView):
queryset = Product.objects.active() # I want to get this value in the functions
serializer_class = ProductSerializer
#condition(etag_func=get_etag_key, last_modified_func=my_last_modified)
def get(self, *args, **kwargs):
return super(ProductsListAPIView, self).get(*args, **kwargs)
What I want to do is get this variable queryset from the main class in the get_etag_key and my_last_modified functions.
Is there any way to go about this?

call parent dispatch before child dispatch django

I have a mixin which beside other things simplifies call of request.user object.
class MyMixin(LoginRequiredMixin, View):
...
leader = False
employee = False
def dispatch(self, request, *args, **kwargs):
self.leader = request.user.is_leader()
self.employee = request.user.is_employee()
return super().dispatch(request, *args, **kwargs)
...
And I have a heir of DetailView which has it's own dispatch method.
class MyDetailView(MyMixin, DetailView):
def dispatch(self, request, *args, **kwargs):
if not self.leader:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
But as you could've told it ain't working. Is there a way to elegantly call parent dispatch method from it's heir?
You could make your attributes into properties so that the order of execution does not matter. Using cached_property will mean that the property is only evaluated once for each request
from django.utils.functional import cached_property
class MyMixin(LoginRequiredMixin, View):
#cached_property
def leader(self):
return self.request.user.is_leader()
#cached_property
def employee(self):
return self.request.user.is_employee()

Django Generic views not working for PUT , GET , UPDATE , PATCH

I have RetrieveUpdateDestroyAPIView view like this.
class TaskRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
lookup_field = 'id'
serializer_class = TasksSerializer
def get_queryset(self):
query_set=Task.objects.get(id=self.kwargs['id'])
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
and my urls like this
path('task_detail/<int:id>', TaskRetrieveUpdateDestroyAPIView.as_view(), name="get_task"),
I am trying to PUT , PATCH , GET but getting same error
{
"detail": "Not found.",
"status_code": 404
}
The issue is in the function get_queryset, It expects a queryset but yours returns a single object, that's what the get function does as described here. So, you need to either set the queryset class field or use the get_queryset function.
You don't need to look up the task object yourself, that's what the generic view does for you. also you don't have to specify the method handlers(get, post, i.e.) yourself, they are already generated because you use RetrieveUpdateDestroyAPIView class. Also, since the lookup field defaults to the primary key(id), so, you could omit that, too
Try this code
class TaskRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
queryset = Task.objects.all()
serializer_class = TasksSerializer
and use pk instead of id
path('task_detail/<int:pk>', TaskRetrieveUpdateDestroyAPIView.as_view(), name="get_task")
or you could leave the lookup field as id and use it in the path function. It's pretty much the same thing, just saving some code

How can I add if statement to a deleteview? CBV django

Hey I want to add if statement and according to it decide if to delete the object or not.
I could not find it online.
In general how can I add if statements to any CBV including Update for example..
This is my DeleteView func:
class PostDeleteView(LoginRequiredMixin, DeleteView):
model = Post
success_url = reverse_lazy('TheApp:post_list')
EDIT! THE SOLUTION THAT WORKED FOR ME:(Thanks to AKX)
def delete(self, request, *args, **kwargs):
if (Post.author == request.user.username):
return super().delete(request, *args, **kwargs)
else:
return HttpResponse('You are not the owner of this Post! You can not delete it!')
Well, as you know, CBVs' methods map to HTTP methods, so just override delete() and add your condition:
class SomeView(..., DeleteView, ...):
def delete(self, request, *args, **kwargs):
if request.GET.get('really') != 'true':
return HttpResponse('I knew you were just kidding!')
return super().delete(request, *args, **kwargs)

Can I redirect to another url in a django TemplateView?

I have a url mapping that looks like this:
url(r'^(?P<lang>[a-z][a-z])/$', MyTemplateView.as_view()),
There are only a few values that I accept for the lang capture group, that is: (1) ro and (2) en. If the user types http://server/app/fr/, I want to redirect it to the default http://server/app/en/.
How can I do this since MyTemplateView only has a method that is expected to return a dictionary?
def get_context_data(self, **kwargs):
return { 'foo': 'blah' }
I know this question is old, but I've just done this myself. A reason you may think you want to do it in get_context_data is due to business logic, but you should place it in dispatch.
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated():
return redirect('home')
return super(MyTemplateView, self).dispatch(request, *args, **kwargs)
Keep your business logic in your dispatch and you should be golden.
Why only get_context_data?
Just set up your get handler to do a redirect if necessary.
def get(self, request, lang):
if lang == 'fr':
return http.HttpResponseRedirect('../en')
return super(MyTemplateView, self).get(request, lang)
A note from the future: it's now possible and probably simpler just to use RedirectView.
This worked for me using an UpdateView class in Django 3.1:
def get(self, request, *args, **kwargs):
if 1 == 1:
return HttpResponseRedirect(reverse_lazy("view_name_here"))
else:
return super().get(request, *args, **kwargs)
To determine this, I analyzed its base class (Cmd+Click in PyCharm), where I found the base method:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, *args, **kwargs)
You can find this and other methods in the Django source code: django/views/generic/edit.py