Django 将基于类的通用视图DetailView与模型表单一起使用会发现一个错误-如何继续?

Django 将基于类的通用视图DetailView与模型表单一起使用会发现一个错误-如何继续?,django,django-generic-views,modelform,bug-reporting,Django,Django Generic Views,Modelform,Bug Reporting,我印象深刻的是,一个功能性网站能够以多么快的速度与教程中的通用视图结合在一起。此外,表单处理的工作流也很好。我使用ModelForm helper类从我制作的模型中创建了一个表单,并且很高兴看到这么多功能结合在一起。当我使用通用的list_detail.object_detail时,我很失望,我能显示的都是单独的字段。我知道ModelForm类包含用于渲染的信息,所以我想将ModelForm与通用视图一起使用 我在stackoverflow上四处打听,想了解一些方向,并感谢几张海报的回答和评论。

我印象深刻的是,一个功能性网站能够以多么快的速度与教程中的通用视图结合在一起。此外,表单处理的工作流也很好。我使用ModelForm helper类从我制作的模型中创建了一个表单,并且很高兴看到这么多功能结合在一起。当我使用通用的list_detail.object_detail时,我很失望,我能显示的都是单独的字段。我知道ModelForm类包含用于渲染的信息,所以我想将ModelForm与通用视图一起使用

我在stackoverflow上四处打听,想了解一些方向,并感谢几张海报的回答和评论。我已经想出了如何让它工作,但在DetailView中有一个bug。解决方案包括一个变通方法

要将模型视图与常规视图一起使用并获取所有字段以自动渲染,请执行以下操作:

创建一个项目,并在其中创建应用程序

如果你有

# inpatients/models.py

class Inpatient(models.Model):
    last_name = models.CharField(max_length=30)
    first_name = models.CharField(max_length=30,blank=True)
    address = models.CharField(max_length=50,blank=True)
    city = models.CharField(max_length=60,blank=True)
    state = models.CharField(max_length=30,blank=True)
    DOB = models.DateField(blank=True,null=True)
    notes = models.TextField(blank=True)

    def __unicode__(self):
        return u'%s, %s %s' % (self.last_name, self.first_name, self.DOB)

class InpatientForm(ModelForm):
    class Meta:
        model = Inpatient

#url.py
从django.conf.url.defaults导入模式,包括url
从django.views.generic导入ListView
从portal.injections.models导入住院患者、住院表单
从portal.injections.views导入FormDetailView
urlpatterns=模式(“”,
(r“^formtest/$”,“门户网站.住院病人.视图.formtest”),
(r“^inpularitics/$”,ListView.as\u视图(
模型=住院患者,模板(名称=住院患者列表(page.html)),
(r'^INDICATIONAL detail/(?P\d+/$),FormDetailView.as_view()),
)
#使用包含
{%block content%}
住院病人
    {对象_列表%中患者的百分比}
  • {%endfor%}
{{住院病人.as_p} {%endblock%} #是的,有点傻。该模板适用于列表视图和详图视图。 #注意表单是如何用一行-{{inspitality.as_p}呈现的
它起作用了。使用基于类的泛型视图的说明非常清楚。使事情正常运行的关键是重新定义get_对象。在“执行额外工作”一节下的文档中,它很好地描述了如何执行此操作,步骤是调用get_对象的原始版本,然后调用额外工作。我意识到返回对象可以是一个ModelForm对象。get_object返回的对象直接进入渲染中的模板。通过获取检索到的Injective对象并通过InjectionForm运行它,可以将其作为表单传递给视图,然后表单会呈现自身

至于bug:DetailView中的bug是get_template_names函数试图从不存在的结构中生成模板名称。在里面 在第127到140行中,我们在SingleObjectTemplateResponseMixin.get_template_名称中有:

127        # The least-specific option is the default <app>/<model>_detail.html;
128         # only use this if the object in question is a model.
129         if hasattr(self.object, '_meta'):
130             names.append("%s/%s%s.html" % (
131                 self.object._meta.app_label,
132                 self.object._meta.object_name.lower(),
133                 self.template_name_suffix
134             ))
135         elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
136             names.append("%s/%s%s.html" % (
137                 self.model._meta.app_label,
138                 self.model._meta.object_name.lower(),
139                 self.template_name_suffix
140             ))
127#最不具体的选项是默认选项,
, 
)


我应该怎么做才能报告这个错误呢?

我相信你是对的。这是一个错误,它源于ModelForm和Models都有一个_meta属性。每当从包含_meta属性的
get\u object()
返回对象时,就会出现同样的错误

get\u对象
不必返回模型实例。您可以通过查看
DetailView
的源代码并读取其docstring来确认这一点:

类详细视图(SingleObjectTemplateResponseMixin,BaseDetailView):
"""
渲染对象的“细节”视图。
默认情况下,这是从“self.queryset”中查找的模型实例,但是
视图将通过重写“self.get_object()”,支持显示*any*对象。
"""
请注意,doc字符串明确表示任何对象都受重写self.get\u object()的支持

另一个确凿的证据来自此bug本身发生的位置,即
SingleObjectTemplateResponseMixin
get\u template\u names方法

    # The least-specific option is the default <app>/<model>_detail.html;
    # only use this if the object in question is a model.
    if hasattr(self.object, '_meta'):
        names.append("%s/%s%s.html" % (
            self.object._meta.app_label,
            self.object._meta.object_name.lower(),
            self.template_name_suffix
        ))
    elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
        names.append("%s/%s%s.html" % (
            self.model._meta.app_label,
            self.model._meta.object_name.lower(),
            self.template_name_suffix
        ))
#最不具体的选项是默认选项


要回答关于如何报告错误的问题,您应该遵循中详述的指导原则。

我认为这不是错误,我确实认为
get\u object
应该始终返回模型实例,而不是
ModelForm
实例。尝试使用。我认为这是一个bug,有几个原因。文件没有说它是无效的。赋值前的有效数据测试测试是否存在_meta而不是实际字段。正在查找模板的例程未找到模板。此外,基于“不要重复您自己”的原则,ModelForm应该能够交付到模板进行渲染。我同意编辑/删除问题。我设想一个自动显示,因为我在该页面上跟随控件,以显示编辑/删除功能。当然,我将尽可能多地使用通用视图。我很感激你证实了我对什么应该被允许的感觉。如果Django采用许多项目的方式,它将增加额外的复杂性,然后当达到临界点时,将出现一种更简单、允许更大功能的重写。我们已经从基于函数到基于类。我相信很多Django已经经历过了。谢谢,史蒂文仍然不相信这是一个错误。您不应该使用
DetailView
,因为
FormView
更适合一件事。至于
get\u template\u names
他们可以使用
isinstance
进行测试,在这种情况下,您应该返回模型实例以确定模板名称。通过这种方式,您可以使用
\u meta
返回任何内容,并能够获取模板名称。除了形式。你应该使用表单视图。这是一个bug,因为它会发生在任何一个拥有非模型的_元实例的类中。它不必是一个form类(更适合使用FormView)。
127        # The least-specific option is the default <app>/<model>_detail.html;
128         # only use this if the object in question is a model.
129         if hasattr(self.object, '_meta'):
130             names.append("%s/%s%s.html" % (
131                 self.object._meta.app_label,
132                 self.object._meta.object_name.lower(),
133                 self.template_name_suffix
134             ))
135         elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
136             names.append("%s/%s%s.html" % (
137                 self.model._meta.app_label,
138                 self.model._meta.object_name.lower(),
139                 self.template_name_suffix
140             ))
    # The least-specific option is the default <app>/<model>_detail.html;
    # only use this if the object in question is a model.
    if hasattr(self.object, '_meta'):
        names.append("%s/%s%s.html" % (
            self.object._meta.app_label,
            self.object._meta.object_name.lower(),
            self.template_name_suffix
        ))
    elif hasattr(self, 'model') and hasattr(self.model, '_meta'):
        names.append("%s/%s%s.html" % (
            self.model._meta.app_label,
            self.model._meta.object_name.lower(),
            self.template_name_suffix
        ))