我正在做以下操作,当用户沿着黄金路径行进时,它可以很好地工作:
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
的调用会导致未处理的唯一性约束违规。
所以,我的问题是:在Klass.duplicate
生命周期中,我应该在哪里调用UpdateView
(unsets pk,重置其他值,然后调用save - 为简洁而省略)?
更新:
看起来像重写post
可能是一种方法来做到这一点。不幸的是,我不能只将表单实例传递给Klass.duplicate
,因为默认情况下它的字段为空。
我想出的解决方案是通过ModelForm
向CBV提供form_class
子类,并使用其重写的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