视图中删除功能的防御性编程 Django

Defensive programming for delete function in views Django

提问人:Erik Andersson 提问时间:7/14/2022 最后编辑:Sunderam DubeyErik Andersson 更新时间:7/14/2022 访问量:183

问:

我对 Django 还很陌生,我收到了一些关于我的项目(食谱应用程序)的反馈,我目前正在从我的导师那里得到一些关于防御性编程的反馈。我在 Django 的应用程序视图中创建了一个删除“函数”,他告诉我要重新制作该函数,这样除了食谱的作者之外,其他人都无法删除选定的食谱。我已经在我的 HTML 中包含了对此的身份验证,但他告诉我对我的删除视图做同样的事情。有没有人对我如何以简单的方式实现这一目标有一个很好的解释?

我以前从未在这里问过问题,所以如果我为这样的问题提供了正确的信息,请给我反馈。

这是我今天的删除视图:

def delete_recipe(request, slug):
    """
    View for delete recipe
    """
    recipe = Recipe.objects.get(slug=slug)
    recipe.delete()
    return redirect('home')
python django django-views 防御性编程

评论


答:

1赞 Maxim Danilov 7/14/2022 #1

我知道最好的描述,你该怎么做。它在这里:https://docs.djangoproject.com/en/4.0/topics/auth/default/#django.contrib.auth.decorators.permission_required

对于最佳实践,您应该检查用户是否具有 .object_delete_permission

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

但这还不是全部:

之后,您应该检查这是否是产品的作者:

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

对我来说不清楚,为什么你不用 Django-GCBV 来做。https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#deleteviewDeleteView

这个视图在盒子里给你所有你需要的东西。

而且,当然,尝试仅在 POST 或 DELETE 时删除某些内容。

1赞 willeM_ Van Onsem 7/14/2022 #2

您应该只能使用 POST 或 DELETE 请求删除某些内容,而不能使用 GET 请求,因为 GET 请求应该不会产生副作用。我们可以用 @require_http_methods(...) 装饰器 [Django-doc] 来强制执行。

该视图还应确保用户已登录,方法是使用 @login_required 装饰器 [Django-doc]。

此外,您应该正确过滤,以便只有(或其他字段)可以删除 ,因此:authorRecipe

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')

然而,用户仍然可能需要权限才能删除 s,因为可以使用 @permission_required(...) 装饰器 [Django-doc]Recipe

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')