Đây là 3 decorator dán lên FBV để chặn request trước khi vào logic — tương đương với mixin tương ứng trên CBV (LoginRequiredMixin, PermissionRequiredMixin).
from django.contrib.auth.decorators import login_required, permission_required
from django.views.decorators.http import require_http_methods
@login_required(login_url='/login/')
def profile(request):
return render(request, 'profile.html')
@permission_required('blog.delete_post', raise_exception=True)
@require_http_methods(['POST'])
def delete_post(request, slug):
Post.objects.filter(slug=slug).delete()
return redirect('blog:post-list')Ngắn gọn từng cái: @login_required chưa login thì redirect về LOGIN_URL. @permission_required('app.codename', raise_exception=True) thiếu perm thì raise PermissionDenied (403) thay vì redirect. @require_http_methods(['POST']) method khác trả 405 Method Not Allowed.
Lỗi rất hay gặp: dán @login_required thẳng vào method get của CBV — không có tác dụng, vì Django đi qua dispatch() trước, không qua get trực tiếp. Trên CBV phải dùng mixin LoginRequiredMixin, hoặc nếu muốn giữ decorator thì @method_decorator(login_required, name='dispatch') ở cấp class.
These three decorators sit on FBVs and reject requests before the logic runs — equivalent to mixins on CBVs (LoginRequiredMixin, PermissionRequiredMixin).
from django.contrib.auth.decorators import login_required, permission_required
from django.views.decorators.http import require_http_methods
@login_required(login_url='/login/')
def profile(request):
return render(request, 'profile.html')
@permission_required('blog.delete_post', raise_exception=True)
@require_http_methods(['POST'])
def delete_post(request, slug):
Post.objects.filter(slug=slug).delete()
return redirect('blog:post-list')@login_required→ unauthenticated requests redirect toLOGIN_URL.@permission_required('app.codename', raise_exception=True)→ missing perm raisesPermissionDenied(403) instead of redirecting.@require_http_methods(['POST'])→ any other method returns405 Method Not Allowed.
Pitfall: On CBVs, use mixins or @method_decorator(login_required, name='dispatch'); do not paste @login_required straight onto get — it has no effect because Django goes through dispatch() first.