如何在Django通用UpdateView类中访问用户传入的对象?
动态修改UpdateView的Model和FormClass(无需重写核心逻辑)
嘿,我完全懂你的需求——不想大改现有的UpdateView逻辑,却能根据当前编辑对象的属性动态切换model和form_class对吧?其实利用Django类视图的钩子方法就能轻松实现,不用重写整个视图的核心流程。
核心思路:利用类视图的钩子方法
UpdateView在初始化阶段还拿不到要编辑的对象,所以没法直接在类属性里写判断逻辑。但它提供了多个可重写的钩子方法,我们可以在这些方法里先获取对象,再动态返回对应的model或form_class。
方法一:缓存当前对象,复用判断逻辑
这种方式会先获取对象并存在实例属性中,后续方法可以直接复用,避免重复查询数据库:
from django.views import generic from django.urls import reverse_lazy from .models import Person, Model1, Model2 from .forms import PersonForm, Model1Form, Model2Form from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator @method_decorator(login_required, name='dispatch') class UpdatePeon(generic.UpdateView): template_name = 'appform/Peons/peon_form.html' success_url = reverse_lazy('view_peons') def get_object(self, queryset=None): # 先调用父类方法获取对象,并存到实例属性里 obj = super().get_object(queryset=queryset) self.current_obj = obj return obj def get_model(self): # 根据当前对象的attr1返回对应model if self.current_obj.attr1 == "Attribute1": return Model1 elif self.current_obj.attr1 == "Attribute2": return Model2 # 默认返回原来的Person模型 return Person def get_form_class(self): # 基于model返回对应的form model = self.get_model() if model == Model1: return Model1Form elif model == Model2: return Model2Form return PersonForm def get_queryset(self): # 如果不同model的查询范围不同,也可以在这里动态返回 return self.get_model().objects.all()
方法二:直接在get_form_class中获取对象
如果逻辑比较简单,也可以直接在get_form_class里获取对象,省去缓存步骤(注意:这会触发两次数据库查询,若对象查询开销大,建议用方法一):
@method_decorator(login_required, name='dispatch') class UpdatePeon(generic.UpdateView): template_name = 'appform/Peons/peon_form.html' success_url = reverse_lazy('view_peons') def get_form_class(self): obj = self.get_object() if obj.attr1 == "Attribute1": return Model1Form elif obj.attr1 == "Attribute2": return Model2Form return PersonForm def get_queryset(self): obj = self.get_object() if obj.attr1 == "Attribute1": return Model1.objects.all() elif obj.attr1 == "Attribute2": return Model2.objects.all() return Person.objects.all()
关键说明
- 我们只重写了
get_object、get_model、get_form_class这些钩子方法,完全保留了UpdateView原有的表单验证、保存、跳转等核心逻辑,符合你“不想重写现有视图逻辑”的要求。 - 关于
login_required:类视图中正确的用法是用method_decorator装饰dispatch方法,你原来的login_required = True如果是自定义的权限控制逻辑可以保留,否则建议替换成上述装饰器写法。
内容的提问来源于stack exchange,提问作者Mike Vlad
相关产品推荐
相关产品推荐

