You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何禁止手动输入URL访问,仅允许表单触发对应视图?

解决任务状态切换仅允许表单提交的问题

问题根源

你的done视图未限制请求方法,手动输入URL发起的GET请求也会触发状态修改;同时你尝试的装饰器逻辑完全错误——它在用户已登录时返回404,导致正常表单提交也被拦截。


方案1:直接校验请求方法与参数

from django.http import HttpResponseBadRequest, HttpResponseForbidden

def done(request, pk):
    # 仅接受POST请求
    if request.method != 'POST':
        return HttpResponseBadRequest("仅允许表单提交访问")
    
    # 校验必须携带is_done参数
    if 'is_done' not in request.POST:
        return HttpResponseForbidden("非法请求")
    
    # 关键:确保任务属于当前用户,防止越权
    try:
        task = Tasks.objects.get(pk=pk, user=request.user)
    except Tasks.DoesNotExist:
        return HttpResponseForbidden("无权操作该任务")
    
    task.is_done = request.POST.get('is_done') == 'on'
    task.save()
    # 增加默认跳转地址,避免referer为空时报错
    return redirect(request.META.get('HTTP_REFERER', '/'))

方案2:使用Django表单类(更规范)

定义表单

# forms.py
from django import forms

class TaskDoneForm(forms.Form):
    is_done = forms.BooleanField(required=False)

视图实现

from django.http import HttpResponseBadRequest, HttpResponseForbidden
from django.views.decorators.http import require_POST
from .forms import TaskDoneForm

@require_POST
def done(request, pk):
    form = TaskDoneForm(request.POST)
    if not form.is_valid():
        return HttpResponseForbidden("请求参数非法")
    
    try:
        task = Tasks.objects.get(pk=pk, user=request.user)
    except Tasks.DoesNotExist:
        return HttpResponseForbidden("无权操作该任务")
    
    task.is_done = form.cleaned_data['is_done']
    task.save()
    return redirect(request.META.get('HTTP_REFERER', '/'))

方案3:用自带装饰器限制请求方法

Django内置require_POST装饰器可直接限制视图仅接受POST请求:

from django.views.decorators.http import require_POST
from django.http import HttpResponseForbidden

@require_POST
def done(request, pk):
    if 'is_done' not in request.POST:
        return HttpResponseForbidden("非法请求")
    
    try:
        task = Tasks.objects.get(pk=pk, user=request.user)
    except Tasks.DoesNotExist:
        return HttpResponseForbidden("无权操作该任务")
    
    task.is_done = request.POST.get('is_done') == 'on'
    task.save()
    return redirect(request.META.get('HTTP_REFERER', '/'))

重要提示

  • 必须添加任务归属校验(user=request.user),避免恶意用户构造URL修改他人任务
  • 为redirect设置默认地址,防止HTTP_REFERER为空时抛出异常

内容的提问来源于stack exchange,提问作者Daniil Filippov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:35:07