gpt4 book ai didi

django - 将基于类的通用 View DetailView 与 ModelForm 一起使用揭示了一个错误 - 如何继续?

转载 作者:行者123 更新时间:2023-12-04 15:47:50 26 4
gpt4 key购买 nike

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

我在 stackoverflow 上四处询问以获得一些指导,并感谢几位海报的答案和评论。我已经想出了如何让它工作,但在 DetailView 中有一个错误。该解决方案包括一种解决方法。

要将 ModelView 与通用 View 一起使用并让所有字段自动呈现以下工作:

创建一个项目,并在其中创建应用程序住院患者。

如果你有

# 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


# inpatients/views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from django.views.generic import DetailView
from portal.inpatients.models import *

def formtest(request):
if request.method == 'POST':
form = InpatientForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/inpatients')
else:
form = InpatientForm()
return render_to_response("formtest.html", {'form': form})

class FormDetailView(DetailView):
model=Inpatient
context_object_name='inpatient' # defines the name in the template
template_name_field='inpatient_list_page.html'

def get_object(self):
inpatient=super(FormDetailView,self).get_object()
form=InpatientForm(instance=inpatient)
return form

def get_template_names(self):
return ['inpatient_list_page.html',]


#urls.py

from django.conf.urls.defaults import patterns, include, url
from django.views.generic import ListView
from portal.inpatients.models import Inpatient, InpatientForm
from portal.inpatients.views import FormDetailView

urlpatterns = patterns('',
(r'^formtest/$','portal.inpatients.views.formtest'),
(r'^inpatients/$', ListView.as_view(
model=Inpatient, template_name='inpatient_list_page.html')),
(r'^inpatient-detail/(?P<pk>\d+)/$', FormDetailView.as_view()),
)

# with a template containing

{% block content %}
<h2>Inpatients</h2>
<ul>
{% for aninpatient in object_list %}
<li><a href='/inpatient-detail/{{ aninpatient.id }}/'>
{{ aninpatient }}, id={{ aninpatient.id }}</a></li>
{% endfor %}
</ul>
{{ inpatient.as_p }}
{% endblock %}
# Yeah, kind of hokey. The template is for both the list view and detail view.
# Note how the form is rendered with one line - {{ inpatient.as_p }}

有用。使用基于类的通用 View 的说明位于 https://docs.djangoproject.com/en/1.3/topics/class-based-views/那里的说明很清楚。使事情工作的关键是重新定义 get_object。在“执行额外工作”部分下的文档中,它很好地描述了如何执行此操作,步骤是调用 get_object 的原始版本,然后进行额外工作。我意识到的一点是返回对象可以是一个 ModelForm 对象。 get_object 返回的对象在渲染中直接进入模板。通过获取检索到的住院对象并通过 InpatientForm 运行它,它可以作为表单传递给 View ,然后呈现自身。

关于bug:DetailView 的bug 是get_template_names 函数试图从不存在的结构中创建模板名称。在
https://code.djangoproject.com/browser/django/trunk/django/views/generic/detail.py
在第 127 到 140 行,我们在 SingleObjectTemplateResponseMixin.get_template_names 中有:
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 ))

错误是第 131 行上的代码被执行并以错误消息 <'ModelFormOptions' object has no attribute 'app_label'> 结束。我的结论是 _meta 对象已定义。我想问题是在 ModelForm 中定义了类 Meta 。该 Meta 可能没有设置预期的字段。解决方法只是重写 get_template_names 并返回正确的模板。

我是 Django 和 Python 的新手。我感谢贡献者在我之前提出的以下问题中的回答和评论。 (
Putting links in list_detail.object_list to list_detail.object_detail ,
Using form in object_detail ,
Rolling your own generic views in Django )

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

最佳答案

我相信你是对的。这是一个错误,源于 ModelForm 和 Models 都有一个 _meta 属性。任何时候从 get_object() 返回一个对象都会出现同样的错误。包含一个 _meta 属性。
get_object不必返回 Model 实例。您可以通过查看 DetailView 的来源来确认这一点。并阅读它的文档字符串:

class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
"""
Render a "detail" view of an object.

By default this is a model instance looked up from `self.queryset`, but the
view will support display of *any* object by overriding `self.get_object()`.
"""

请注意,文档字符串明确表示通过覆盖 self.get_object() 支持任何对象。

另一个确凿的证据来自此错误本身发生的位置,即 get_template_names methodSingleObjectTemplateResponseMixin .
    # 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
))

再次查看此代码,注释本身说“如果有问题的对象是模型”。从这个评论我们可以推断出对象并不总是必须是模型。

但是,如果您尝试创建允许某人编辑/创建/删除模型的 View ,您真的应该查看编辑 View ,其中包括 FormView、CreateView、EditView 和 DeleteView。您可以在 https://docs.djangoproject.com/en/1.3/ref/class-based-views/#editing-views 查看更多信息。 .

要回答有关如何报告错误的问题,您应该遵循 https://docs.djangoproject.com/en/1.3/internals/contributing/#reporting-bugs 中详述的指南。 .

关于django - 将基于类的通用 View DetailView 与 ModelForm 一起使用揭示了一个错误 - 如何继续?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6564068/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com