使用 Django UpdateView 子类进行对象复制时处理无效数据
Handle invalid data when using Django UpdateView subclass for object duplication
我正在执行以下操作,当用户沿着黄金路径前进时效果很好:
class MyUpdate(UpdateView)
# ...
class MyDuplicate(MyUpdate):
def get_context_data(self, **kwargs):
context = super(MyDuplicate, self).get_context_data(**kwargs)
context['action'] = "Duplicate"
return context
# where should I call Klass::duplicate?
def form_valid(self, form):
name = form.instance.full_name
video_url = form.instance.video_url
# This doesn't work because it can result in unhandled uniqueness
# constraint violations.
form.instance = Klass.duplicate(
form.instance,
name,
video_url
)
return super(MyDuplicate, self).form_valid(form)
但是,如果用户尝试提交现有的 full_name
(必须是唯一的),那么对 Klass.duplicate
的调用会导致未处理的唯一性约束冲突。
所以,我的问题是:在 UpdateView
生命周期中,我应该在哪里调用 Klass.duplicate
(取消设置 pk,重置其他值,然后调用保存——为简洁起见省略)?
更新:
看起来覆盖 post
可能是一种方法。不幸的是,我不能只将表单实例传递给 Klass.duplicate
,因为默认情况下它的字段是空的。
我想到的解决方案是通过 form_class
向 CBV 提供一个 ModelForm
子类,并使用其覆盖的 is_valid
方法来处理任何潜在的异常并向最终用户。
因此,根据我最初问题中的示例,解决方案如下所示:
class MyDuplicateForm(forms.ModelForm):
class Meta:
model = Klass
fields = [...]
def is_valid(self):
valid = super(MyDuplicateForm, self).is_valid()
if not valid:
return False
try:
self.instance = Klass.duplicate(self.instance)
except Exception as exception:
self._errors[NON_FIELD_ERRORS] = exception
return False
return True
class MyDuplicate(UpdateView):
form_class = MyDuplicateForm
model = klass
我正在执行以下操作,当用户沿着黄金路径前进时效果很好:
class MyUpdate(UpdateView)
# ...
class MyDuplicate(MyUpdate):
def get_context_data(self, **kwargs):
context = super(MyDuplicate, self).get_context_data(**kwargs)
context['action'] = "Duplicate"
return context
# where should I call Klass::duplicate?
def form_valid(self, form):
name = form.instance.full_name
video_url = form.instance.video_url
# This doesn't work because it can result in unhandled uniqueness
# constraint violations.
form.instance = Klass.duplicate(
form.instance,
name,
video_url
)
return super(MyDuplicate, self).form_valid(form)
但是,如果用户尝试提交现有的 full_name
(必须是唯一的),那么对 Klass.duplicate
的调用会导致未处理的唯一性约束冲突。
所以,我的问题是:在 UpdateView
生命周期中,我应该在哪里调用 Klass.duplicate
(取消设置 pk,重置其他值,然后调用保存——为简洁起见省略)?
更新:
看起来覆盖 post
可能是一种方法。不幸的是,我不能只将表单实例传递给 Klass.duplicate
,因为默认情况下它的字段是空的。
我想到的解决方案是通过 form_class
向 CBV 提供一个 ModelForm
子类,并使用其覆盖的 is_valid
方法来处理任何潜在的异常并向最终用户。
因此,根据我最初问题中的示例,解决方案如下所示:
class MyDuplicateForm(forms.ModelForm):
class Meta:
model = Klass
fields = [...]
def is_valid(self):
valid = super(MyDuplicateForm, self).is_valid()
if not valid:
return False
try:
self.instance = Klass.duplicate(self.instance)
except Exception as exception:
self._errors[NON_FIELD_ERRORS] = exception
return False
return True
class MyDuplicate(UpdateView):
form_class = MyDuplicateForm
model = klass