无法弄清楚如何使用通用UpdateView呈现ModelForm

时间:2018-05-19 20:50:05

标签: django django-models django-forms django-templates django-views

当我使用通用UpdateView时,我试图弄清楚ModelForm是如何实例化的。

我已经浏览了django源代码并查看了UpdateView和相关的Form类但我无法看到我们明确传递的任何代码行{{1到instance类的对象。

例如,假设我们ModelFormPostForm,那么我们就写了:

ModelForm

从模型对象渲染表单。

我无法在django源代码中看到类似的代码,并且无法弄清楚form = PostForm(instance=Post.object.get(pk=pk)) 如何填充通用ModelForm 即,在POST表单后提交数据时,如何实例化我的表单的UpdateView属性。

2 个答案:

答案 0 :(得分:2)

instance的{​​{1}}属性在ModelForm

中定义的get_form_kwargs()中实例化

详细说明见下文:

ModelFormMixin视图会继承UpdateView

SingleObjectTemplateResponseMixin, BaseUpdateView进一步继承BaseUpdateViewModelFormMixin
 它还定义了通过发送方式调用的ProcessFormViewget方法 这些postget方法将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())