Защитное программирование для функции delete в представлениях Django
Я довольно новичок в Django, и я получил несколько отзывов для моего проекта (приложение для рецептов), над которым я сейчас работаю, от моего наставника о защитном программировании. Я создал "функцию" удаления в представлениях моего приложения в Django, и он сказал мне переделать эту функцию так, чтобы никто, кроме автора рецепта, не мог удалить выбранный рецепт. Я включил аутентификацию для этого в свой HTML, но он сказал мне сделать то же самое для моего представления удаления. Есть ли у кого-нибудь хорошее объяснение, как я могу добиться этого простым способом?
Я никогда раньше не задавал здесь вопросов, поэтому дайте мне обратную связь, если я предоставил правильную информацию для такого вопроса.
Вот мой взгляд на удаление сегодня:
def delete_recipe(request, slug):
"""
View for delete recipe
"""
recipe = Recipe.objects.get(slug=slug)
recipe.delete()
return redirect('home')
Я знаю лучшее Описание, как вы можете это сделать. Это здесь: 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 DeleteView
.
https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#deleteview
Этот вид даст вам все, что нужно, в коробке.
И, конечно, попробуйте удалить что-то только по POST или DELETE.
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].
Представление также должно убедиться, что пользователь вошел в систему, используя декоратор @login_required
[Django-doc].
Кроме того, вы должны правильно фильтровать, чтобы только author
(или какое-то другое поле) могло удалить Recipe
, поэтому:
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')
Однако может быть и так, что пользователю требуется разрешение на удаление Recipe
вообще, для этого можно использовать декоратор @permission_required(…)
[Django-doc]:
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')