Django Admin自定义页面的DetailsView实现CRUD遇405错误求助
问题解答
一、解决DetailView返回405状态码的问题
你的代码返回405是因为Django的DetailView默认只处理GET请求,它没有内置POST请求的处理逻辑,直接在get_context_data里写POST分支根本不会被触发,反而会因为视图不允许POST方法返回405。
修复方案很简单:把POST请求的处理逻辑移到重写的post方法里,而不是放在get_context_data中:
from django.views.generic import DetailView from django.http import HttpResponseRedirect from django.urls import reverse from .models import Student, AddressDetails, Education from .forms import StudentUpdateForm from django.contrib import admin class StudentView(DetailView): template_name = 'admin/Student/student/details.html' model = Student def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) student = context['object'] # 添加上下文数据 context['address_details'] = AddressDetails.objects.filter(student=student) context['educations'] = Education.objects.filter(student=student) context.update(admin.site.each_context(self.request)) context['opts'] = self.model._meta # 把更新表单添加上下文,用于页面渲染 context['student_form'] = StudentUpdateForm(instance=student) return context def post(self, request, *args, **kwargs): self.object = self.get_object() student = self.object action = request.POST.get('action', '') student_form = StudentUpdateForm(request.POST, instance=student) if student_form.is_valid(): student_form.save() return HttpResponseRedirect(reverse('student_detail', args=[student.pk])) # 表单验证失败时,返回原页面并携带错误信息 context = self.get_context_data(**kwargs) context['student_form'] = student_form return self.render_to_response(context)
同时要确保模板里的表单配置正确,必须包含POST方法和CSRF令牌:
<form method="post"> {% csrf_token %} {{ student_form.as_p }} <button type="submit" name="action" value="update">更新学生信息</button> </form>
二、Django Admin的DetailsView中是否可以执行CRUD操作?
可以,但默认的Admin详情页(对应ModelAdmin.detail_view)只提供查看功能,要实现CRUD需要自己扩展:
- 更新操作:像上面那样重写视图的POST方法,在详情页嵌入更新表单提交
- 删除操作:在详情页添加删除按钮,提交POST请求到删除视图,或者直接在当前视图中处理删除逻辑
- 创建操作:详情页针对单个对象,创建一般在列表页,但如果要关联创建(比如给当前学生加教育记录),可以在详情页嵌入关联对象的创建表单,处理POST请求保存
三、自定义Django Admin报表页面实现CRUD操作的思路
如果你的报表是自定义Admin页面,按以下步骤来:
- 注册自定义视图到Admin:通过
ModelAdmin.get_urls()添加自定义URL,映射到你的视图 - 视图内处理CRUD逻辑:
- GET请求:渲染报表数据和各类CRUD表单
- POST请求:根据提交的
action参数(比如create/update/delete)执行对应操作
- 统一Admin样式:用
admin.site.each_context(request)获取Admin的上下文变量,让自定义页面和Admin样式保持一致 - 权限控制:利用Admin的权限系统,在视图里检查用户是否有对应模型的CRUD权限,比如
request.user.has_perm('app.change_student')
示例:把自定义报表视图注册到Student Admin
from django.contrib import admin from django.urls import path from .models import Student from .views import StudentReportView @admin.register(Student) class StudentAdmin(admin.ModelAdmin): def get_urls(self): urls = super().get_urls() custom_urls = [ path('report/', self.admin_site.admin_view(StudentReportView.as_view()), name='student-report'), ] return custom_urls + urls
之后在StudentReportView里,参考前面的StudentView写法,根据需求添加创建、删除的处理分支即可。
内容的提问来源于stack exchange,提问作者Subas Adhikari
相关产品推荐
相关产品推荐

