ModelForm 的instance 属性在get_form_kwargs() 中实例化,在ModelFormMixin 中定义
详细解释见下:
UpdateView 视图继承 SingleObjectTemplateResponseMixin, BaseUpdateView
BaseUpdateView进一步继承ModelFormMixin和ProcessFormView
它还定义了通过 dispatch
调用的 get 和 post 方法
这些get 和post 方法将object 属性设置为当前模型对象。下面是来自 django 文档的代码 sn-p:
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)
get 和 post 方法也调用父级的 get 和 post 方法,即在 ProcessFormView 中定义的 get 和 post
在 GET 请求期间
在ProcessFormView 中定义的get 方法调用在FormMixin 下覆盖的get_context_data(),它进一步调用get_form() 以返回要在视图中使用的表单实例。
def get_context_data(self, **kwargs):
"""
Insert the form into the context dict.
"""
if 'form' not in kwargs:
kwargs['form'] = self.get_form()
return super(FormMixin, self).get_context_data(**kwargs)
get_form() 调用位于ModelFormMixin 和FormMixin 中的get_form_kwargs(),但由于ModelFormMixin 继承自FormMixin,因此ModelFormMixin 中定义的方法将覆盖FormMixin 中定义的方法。这个get_form_kwargs() 方法首先调用父/父的方法,然后将表单的instance 属性设置为当前模型对象,即self.object(或简单的object)。
以下文档中的代码 sn-p :
def get_form_kwargs(self): #defined in ModelFormMixin class
"""
Returns the keyword arguments for instantiating the form.
"""
kwargs = super(ModelFormMixin, self).get_form_kwargs()
if hasattr(self, 'object'):
kwargs.update({'instance': self.object})
return kwargs
然后使用模型对象的属性呈现表单
在 POST 请求期间:
如前所述(参见第一个代码 sn-p),就像get() 一样,post() 方法也将object 属性设置为当前模型对象,即self.object=self.get_object()。 (get_object() 继承自 SingleObjectMixin 类)
然后它调用ProcessFormView的post方法,即使用get_form() 方法创建form 实例的父类。 (就像 get_context_method 在get 请求的情况下所做的那样)
get_form() 调用get_form_kwargs 进一步将表单的instance 属性设置为在第一个post 方法调用中实例化的self.object。
代码如下:
class ProcessFormView(View):
"""
A mixin that renders a form on GET and processes it on POST.
"""
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates a blank version of the form.
"""
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance with the passed
POST variables and then checked for validity.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
# PUT is a valid HTTP verb for creating (with a known URL) or editing an
# object, note that browsers only support POST for now.
def put(self, *args, **kwargs):
return self.post(*args, **kwargs)
接下来,根据基本约束验证表单,这是通过调用从 BaseForm 类继承的 form.is_valid() 方法来完成的。
这是非常重要的一步,因为此时,instance 对象的属性会更新为表单中 POST 的数据。
这一切都是通过以下调用堆栈实现的:
form.is_valid() 调用 -> errors 属性 -> 调用 full_clean() -> _clean_fields() -> _clean_form() -> _post_clean()
_post_clean() 从 POST 构造 instance通过调用construct_instance_method获取数据
要更好地理解这些函数,请阅读is_valid() here 的BaseForm 类和_post_clean() here 的BaseModelForm 类