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

Popular posts from this blog

c++ - Is it possible to compile a VST on linux? -

java - Output of Eclipse is rubbish -

jquery - Confused with JSON data and normal data in Django ajax request -