我遇到了我想要这样的东西的情况。这是我想出的(请注意,如果您尝试将其用作更新视图并且找不到请求的对象,它将表现为创建视图而不是抛出 404):
from django.views.generic.detail import SingleObjectTemplateResponseMixin
from django.views.generic.edit import ModelFormMixin, ProcessFormView
class CreateUpdateView(
SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView
):
def get_object(self, queryset=None):
try:
return super(CreateUpdateView,self).get_object(queryset)
except AttributeError:
return None
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(CreateUpdateView, self).post(request, *args, **kwargs)
事实证明UpdateView 和CreateView 继承自完全相同的类和mixin。唯一的区别在于 get/post 方法。以下是它们在 Django 源代码 (1.8.2) 中的定义方式:
class BaseCreateView(ModelFormMixin, ProcessFormView):
"""
Base view for creating an new object instance.
Using this base class requires subclassing to provide a response mixin.
"""
def get(self, request, *args, **kwargs):
self.object = None
return super(BaseCreateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = None
return super(BaseCreateView, self).post(request, *args, **kwargs)
class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
"""
View for creating a new object instance,
with a response rendered by template.
"""
template_name_suffix = '_form'
class BaseUpdateView(ModelFormMixin, ProcessFormView):
"""
Base view for updating an existing object.
Using this base class requires subclassing to provide a response mixin.
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
return super(BaseUpdateView, self).post(request, *args, **kwargs)
class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
"""
View for updating an object,
with a response rendered by template.
"""
template_name_suffix = '_form'
如您所见,CreateView 的 get 和 post 方法设置为 self.object = None,而 UpdateView 将其设置为 self.get_object()。我所做的只是将这两者结合到我的 CreateUpdateView.get_object 方法中,该方法尝试调用父类的 get_object 并返回 None,而不是在没有对象时引发异常。
要在用作更新视图时提供 404 页面,您可以覆盖 as_view 并传递一个 update_only 布尔参数。如果update_only 是True 并且视图找不到对象,则引发404。