Home > Enterprise >  Defensive programming for delete function in views Django
Defensive programming for delete function in views Django

Time:07-15

I am fairly new to Django, and I got some feedback for my project (recipe app) that I am currently working on from my mentor about defensive programming. I have created a delete "function" in my app views in Django, and he told me to remake the function so no one else than the author of the recipe could ever delete the selected recipe. I have included authentication for this in my HTML but he told me to do the same for my delete view. Does anyone have a good explanation for how I could achieve this in a simple way?

I have never before asked a question here so give me feedback if I have provided the right information for a question like this.

Here is my delete view today:

def delete_recipe(request, slug):
    """
    View for delete recipe
    """
    recipe = Recipe.objects.get(slug=slug)
    recipe.delete()
    return redirect('home')

CodePudding user response:

You should only be capable to delete something with a POST or DELETE request, not with a GET request, since GET requests are supposed not to have side-effects. We can enforce this with the @require_http_methods(…) decorator [Django-doc].

The view should also ensure that the user is logged in, by using the @login_required decorator [Django-doc].

Furthermore you should filter properly such that only the author (or some other field) can delete the Recipe, so:

from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods

@require_http_methods(['DELETE', 'POST'])
@login_required
def delete_recipe(request, slug):
    """
    View for delete recipe
    """
    Recipe.objects.filter(slug=slug, author=request.user).delete()
    return redirect('home')

It might however still be possible that the user requires a permission to remove Recipes in general, for that the @permission_required(…) decorator [Django-doc] can be used:

from django.contrib.auth.decorators import login_required, permission_required
from django.views.decorators.http import require_http_methods

@require_http_methods(['DELETE', 'POST'])
@login_required
@permission_required('app_name.delete_recipe')
def delete_recipe(request, slug):
    """
    View for delete recipe
    """
    Recipe.objects.filter(slug=slug, author=request.user).delete()
    return redirect('home')

CodePudding user response:

I know the best Description, how you can do it. It is here: https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.decorators.permission_required

For best practice, you should check if user has object_delete_permission.

@permission_required('app_name.delete_reciepe', login_url='/name_of_login_page/')
def delete_recipe(request, slug):
    ...

But it is not all:

After that you should check if this is author of product:

...
recipe = Recipe.objects.get(slug=slug)
if request.user.pk == recipe.author_pk
    recipe.delete()
...

For me is not clear, why you dont do it with Django-GCBV DeleteView. https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#deleteview

This view give you all, that you need, in box.

And, of Course, try to delete something only on POST or DELETE.

  • Related