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

如何在Django类视图中有效使用PUT和DELETE HTTP方法?

Django类视图实现PUT/DELETE请求的CRUD方案

一、URL路由配置

按照需求映射URL规则,区分集合操作(列表/创建)和单个资源操作(详情/更新/删除):

在backendapp/urls.py中添加:

from django.urls import path
from .views import CategoryView, CategoryDetailView

urlpatterns = [
    # 分类列表页 + 创建页
    path('categories/', CategoryView.as_view(), name='category-list'),
    path('categories/create/', CategoryView.as_view(), name='category-create'),
    # 分类详情页 + 更新 + 删除
    path('categories/<int:pk>/', CategoryDetailView.as_view(), name='category-detail'),
]

二、拆分视图类(职责更清晰)

将原CategoryView拆分为两个类,分别处理不同场景的请求:

1. 集合操作视图(列表+创建)

from django.shortcuts import render, redirect
from django.views import View
from .models import Category
from .forms import CategoryForm  # 需提前定义ModelForm

class CategoryView(View):
    template_name = 'backendapp/pages/category/categories.html'

    def get(self, request):
        # 渲染分类列表+创建表单
        categories = Category.objects.all()
        form = CategoryForm()
        return render(request, self.template_name, {
            'categories': categories,
            'form': form
        })

    def post(self, request):
        # 处理创建分类的POST请求
        form = CategoryForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('category-list')
        # 验证失败,返回带错误的页面
        categories = Category.objects.all()
        return render(request, self.template_name, {
            'categories': categories,
            'form': form
        })

2. 单个资源操作视图(详情+更新+删除)

from django.shortcuts import get_object_or_404, render, redirect
from django.views import View
from django.http import QueryDict
from .models import Category
from .forms import CategoryForm

class CategoryDetailView(View):
    template_name = 'backendapp/pages/category/category_detail.html'

    def get(self, request, pk):
        # 渲染单个分类的详情+更新表单
        category = get_object_or_404(Category, pk=pk)
        form = CategoryForm(instance=category)
        return render(request, self.template_name, {
            'category': category,
            'form': form
        })

    def put(self, request, pk):
        # 处理更新分类的PUT请求
        category = get_object_or_404(Category, pk=pk)
        # Django默认不解析PUT数据到request.POST,需手动解析body
        put_data = QueryDict(request.body)
        form = CategoryForm(put_data, instance=category)
        
        if form.is_valid():
            form.save()
            return redirect('category-list')
        # 验证失败,返回详情页带错误
        return render(request, self.template_name, {
            'category': category,
            'form': form
        })

    def delete(self, request, pk):
        # 处理删除分类的DELETE请求
        category = get_object_or_404(Category, pk=pk)
        category.delete()
        return redirect('category-list')

三、ModelForm定义(必填)

创建backendapp/forms.py,定义与Category模型绑定的表单:

from django.forms import ModelForm
from .models import Category

class CategoryForm(ModelForm):
    class Meta:
        model = Category
        fields = ['name']  # 替换为你的Category模型实际字段

四、前端提交PUT/DELETE请求的两种方式

浏览器原生表单仅支持GET/POST,需通过以下方式模拟PUT/DELETE:

1. 使用POST + _method参数(Django内置支持)

Django的CommonMiddleware会自动识别_method参数,将POST请求转换为对应HTTP方法:

删除按钮表单

<form action="{% url 'category-detail' category.pk %}" method="POST">
    {% csrf_token %}
    <input type="hidden" name="_method" value="DELETE">
    <button type="submit" onclick="return confirm('确定删除?')">删除分类</button>
</form>

更新分类表单

<form action="{% url 'category-detail' category.pk %}" method="POST">
    {% csrf_token %}
    <input type="hidden" name="_method" value="PUT">
    {{ form.as_p }}
    <button type="submit">更新分类</button>
</form>

2. AJAX异步请求

适合单页或异步场景,直接发送PUT/DELETE请求:

// 更新分类的AJAX示例
document.querySelector('#update-form').addEventListener('submit', function(e) {
    e.preventDefault();
    const pk = this.dataset.pk;
    const formData = new FormData(this);

    fetch(`/backendapp/categories/${pk}/`, {
        method: 'PUT',
        headers: {
            'X-CSRFToken': getCookie('csrftoken') // 必须携带CSRF令牌
        },
        body: formData
    }).then(res => {
        if (res.ok) location.href = '/backendapp/categories/';
        else alert('更新失败');
    });
});

// 获取CSRF令牌的工具函数
function getCookie(name) {
    let value = null;
    if (document.cookie) {
        const cookies = document.cookie.split(';');
        for (let cookie of cookies) {
            const [key, val] = cookie.trim().split('=');
            if (key === name) value = decodeURIComponent(val);
        }
    }
    return value;
}

五、关键注意事项

  • 确保django.middleware.common.CommonMiddleware和django.middleware.csrf.CsrfViewMiddleware在settings.py中间件列表中(默认已开启)。
  • PUT请求的数据不会自动存入request.POST,必须手动解析request.body。
  • 使用get_object_or_404自动处理主键不存在的情况,避免抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:13:17