当我使用通用UpdateView
时,我试图弄清楚ModelForm是如何实例化的。
我已经浏览了django源代码并查看了UpdateView
和相关的Form
类但我无法看到我们明确传递的任何代码行{{1到instance
类的对象。
例如,假设我们ModelForm
为PostForm
,那么我们就写了:
ModelForm
从模型对象渲染表单。
我无法在django源代码中看到类似的代码,并且无法弄清楚form = PostForm(instance=Post.object.get(pk=pk))
如何填充通用ModelForm
即,在POST表单后提交数据时,如何实例化我的表单的UpdateView
属性。
答案 0 :(得分:2)
instance
的{{1}}属性在ModelForm
get_form_kwargs()
中实例化
详细说明见下文:
ModelFormMixin
视图会继承UpdateView
SingleObjectTemplateResponseMixin, BaseUpdateView
进一步继承BaseUpdateView
和ModelFormMixin
它还定义了通过发送方式调用的ProcessFormView
和get
方法
这些post
和get
方法将post
属性设置为当前模型对象。以下是django docs的代码片段:
object
get和post方法还调用父级的get和post方法,即在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请求期间
ProcessFormView
中定义的get
方法调用ProcessFormView
覆盖get_context_data()
下的FormMixin
进一步调用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()
调用get_form_kwargs()
ModelFormMixin
以及FormMixin
,但由于ModelFormMixin
继承自FormMixin
,因此定义的方法ModelFormMixin
会覆盖FormMixin
中定义的那个。这个get_form_kwargs()
方法首先调用super / parent的方法,然后将表单的instance
属性设置为当前模型对象,即self.object
(或简称为object
)。 />
以下文档中的代码段:
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请求期间:
如前所述(请参阅第一个代码段),就像get()
一样,post()
方法也会将object
属性设置为当前模型对象,即self.object=self.get_object()
。 (get_object()继承自SingleObjectMixin
类)
然后它调用post
的{{1}}方法,即。使用ProcessFormView
方法创建form
实例的父类。 (就像get_form()
请求时get_context_method一样
get
调用get_form()
进一步将表单的get_form_kwargs
属性设置为在instance
方法调用中实例化的self.object
。
以下代码段:
post
接下来,根据基本约束验证表单,这是通过调用从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)
类继承的form.is_valid()
方法来完成的。
这是非常重要的一步,因为此时,BaseForm
对象的属性将更新为表单中POST的数据。
这一切都是通过以下一堆电话来实现的:
instance
来电 - > form.is_valid()
属性 - >调用errors
- > full_clean()
- > _clean_fields()
- > _clean_form()
_post_clean()
通过调用_post_clean()
instance
数据构建POST
为了理解这些功能,请更好地阅读construct_instance_method
here BaseForm
课程is_valid()
和BaseModelForm
课程_post_clean()
here
答案 1 :(得分:0)
我想你可能正在寻找这种方法
FormMixin.get_form_kwargs()
以下是Github的来源repo:
def get_form_kwargs(self):
...
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
如您所见,如果请求是POST,则来自POST和FILES的数据 从此方法返回,然后用于实例化表单,正如您在下面的第二个代码段中看到的那样source:
def get_form(self, form_class=None):
...
return form_class(**self.get_form_kwargs())