django - Using class based generic view DetailView with a ModelForm reveals a bug - how to proceed? -
i've been impressed how rapidly functional website can go generic views in tutorials. also, workflow form processing nice. used modelform helper class create form model made , delighted see functionality came together. when used generic list_detail.object_detail disappointed display fields individually. knew modelform class contained information rendering, wanted use modelform generic view.
i asking around on stackoverflow direction, , appreciate answers , comments several posters. i've figured out how work, there bug in detailview. solution includes workaround.
to use modelview generic view , fields render automatically following works:
create project, , in create application inpatients.
if have
# 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 and
# inpatients/views.py django.http import httpresponse, httpresponseredirect django.shortcuts import render_to_response django.views.generic import detailview 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 name in 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',] and
#urls.py django.conf.urls.defaults import patterns, include, url django.views.generic import listview portal.inpatients.models import inpatient, inpatientform 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()), ) # template containing {% block content %} <h2>inpatients</h2> <ul> {% 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. template both list view , detail view. # note how form rendered 1 line - {{ inpatient.as_p }} it works. instructions using class based generic views lives @ https://docs.djangoproject.com/en/1.3/topics/class-based-views/ instructions there pretty clear. key making things work redefine get_object. in documentation under section "performing work" nicely describes how this, steps being call original version of get_object, , work. bit realized return object can modelform object. object get_object returns goes straight template in render. taking retrieved inpatient object , running through inpatientform can passed view form renders itself.
as bug: bug in detailview get_template_names function tries make template name structure not exist. in https://code.djangoproject.com/browser/django/trunk/django/views/generic/detail.py on lines 127 140 have within singleobjecttemplateresponsemixin.get_template_names:
127 # least-specific option default <app>/<model>_detail.html; 128 # use if object in question 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') , 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 error code on line 131 executed , dies error message <'modelformoptions' object has no attribute 'app_label'>. conclude _meta object defined. suppose problem in modelform class meta defined. meta doesn't have fields set expected. workaround rewrite get_template_names , return correct template.
i'm new django , python. appreciate answers , comments contributors @ following previous questions asked. ( putting links in list_detail.object_list list_detail.object_detail, using form in object_detail, rolling own generic views in django)
what should report bug?
you right believe. bug stems fact both modelform , models have _meta attribute. same bug exhibit anytime object returned get_object() contains _meta attribute.
get_object not have return model instance. can confirm looking @ source detailview , reading it's docstring:
class detailview(singleobjecttemplateresponsemixin, basedetailview): """ render "detail" view of object. default model instance looked `self.queryset`, view support display of *any* object overriding `self.get_object()`. """ notice doc string explicitly says object supported overriding self.get_object().
another piece of corroborating evidence location bug occurs get_template_names method of singleobjecttemplateresponsemixin.
# least-specific option default <app>/<model>_detail.html; # use if object in question 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') , 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 )) again looking @ code, comment "if object in question model". comment can infer object doesn't have model.
however if trying create view allows edit/create/delete model should have @ editing views include formview, createview, editview , deleteview. can see more information these @ https://docs.djangoproject.com/en/1.3/ref/class-based-views/#editing-views.
to answer question how report bug, should follow guidelines detailed @ https://docs.djangoproject.com/en/1.3/internals/contributing/#reporting-bugs.
Comments
Post a Comment