2011-07-03 13 views
6

İşlevsel bir web sitesinin öğreticilerdeki genel görünümlerle ne kadar hızlı bir şekilde birlikte olabileceğinden çok etkilendim. Ayrıca, form işleme için iş akışı güzel. Yaptığım bir modelden bir form oluşturmak için ModelForm yardımcı sınıfını kullandım ve çok fazla işlevin bir araya geldiğini görmek beni çok mutlu etti. Ben jenerik list_detail.object_detail kullandığınızda ben görüntüleyebileceğim tüm tek tek alanlar vardı hayal kırıklığına uğradım. ModelForm sınıfının oluşturma için bilgi içerdiğini biliyordum, bu yüzden ModelForm'u genel bir görünümle kullanmak istedim.Sınıf tabanlı genel görünümü kullanarak ModelView ile DetailView bir hatayı ortaya çıkarır - nasıl devam edilir?

Bazı yönleri almak için stackoverflow üzerinde soruyordum ve birkaç posterin cevaplarını ve yorumlarını takdir ediyorum. Bunu nasıl çalıştıracağımı anladım, ama DetailView'da bir hata var. Çözüm bir geçici çözüm içerir.

jenerik manzaralı bir Modelview kullanmak ve otomatik olarak aşağıdaki işleri işlemek için tüm alanları almak için:

Proje oluşturma ve uygulama yatan oluşturmak içinde.

Eğer

# 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 

ve

# 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',] 

ve

çalıştığını
#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 }} 

varsa. Sınıf tabanlı genel görünümleri kullanma talimatları, https://docs.djangoproject.com/en/1.3/topics/class-based-views/ Talimatında geçerlidir. Talimatlar oldukça açıktır. İşleri yapmanın anahtarı get_object'i yeniden tanımlamaktır. "Ekstra çalışma yapma" bölümünün altındaki dokümantasyonda, bunun nasıl yapılacağını, get_object'in orijinal sürümünü çağırmak için gereken adımları ve daha sonra ek çalışmayı açıklar. Anladığım bit, dönüş nesnesinin bir ModelForm nesnesi olabileceğidir. Get_object öğesinin döndürdüğü nesne, bir render içindeki şablona doğrudan gider. Alınan yatan nesneyi alarak ve onu InpatientForm aracılığıyla çalıştırarak, kendisini daha sonra ortaya çıkaran bir form olarak görülebilir.

Hata hakkında: DetailView'daki hata, get_template_names işlevinin, var olmayan bir yapıdan şablon adı oluşturmaya çalışmasıdır. satırlarda https://code.djangoproject.com/browser/django/trunk/django/views/generic/detail.py 140 127 biz SingleObjectTemplateResponseMixin.get_template_names içinde vardır:

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   )) 

hata hattı 131 üzerindeki kod yürütülür ve < 'ModelFormOptions' nesnesi niteliği 'app_label' sahip bir hata iletisi ile ölür olduğu >. _meta nesnesinin tanımlandığı sonucuna varıyorum. Problemin, ModelForm'da Meta sınıfının tanımlanması olduğunu düşünüyorum. Bu Meta muhtemelen beklenen alanlara sahip değil. Çözüm, sadece get_template_names 'i yeniden yazıp doğru şablonu döndürmektir.

Django ve Python’da yeni. Katkıda bulunanların daha önce sorduğum soruların cevaplarını ve yorumlarını memnuniyetle karşılıyorum. ( Putting links in list_detail.object_list to list_detail.object_detail, Using form in object_detail, Rolling your own generic views in Django)

Ben hatayı bildirmek için ne yapmalıyım?

+0

Bunun bir hata olduğunu sanmıyorum, ben get_object' hep modeli örneği değil 'ModelForm' örneği dönmelidir' düşünüyorum. [Düzenleme CBV] kullanılarak deneyin (https://docs.djangoproject.com/en/dev/ref/class-based-views/#editing-views). –

+0

Birkaç sebepten dolayı bir hata olduğunu düşünüyorum. Belgeler geçersiz olduğunu söylemiyor. Ödev testinden önce geçerli veriler için test, gerçek alanlardan ziyade _meta'nın varlığını test eder. Şablonu arayan rutin, şablonu bulamadı. Ek olarak, Kendinizi Tekrar Etmeyin prensibine göre, ModelForm, işleme için bir şablona teslim edilebilmelidir. – kd4ttc

cevap

2

Haklısınız. Bu, hem ModelForm hem de Modellerin bir _meta özniteliğine sahip olmasından kaynaklanan bir hatadır.Bu, aynı hata her zaman bir nesne bir _meta bir özellik var get_object() döndürülür kendisini gösterecektir.

get_object Model örneği dönmek zorunda değildir. Sen DetailView için kaynak arayan ve docstringe oluyor okuyarak bu onaylayabilirsiniz:

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()`. 
    """ 

Bildirimi doc dize açıkça herhangi bir nesne self.get_object geçersiz kılarak desteklendiğini söylüyor().

Düzeltmenin kanıtlarından başka bir kısmı, bu hatanın oluştuğu yer olan 'un SingleObjectTemplateResponseMixin olmasıdır.

# 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 
     )) 

Yine bu kodun bakarak, yorum kendisini "Söz konusu nesne modeli ise" derler. Bu yorumdan, nesnenin her zaman bir model olması gerekmediğini söyleyebiliriz. Birinin gerçekten FormView, CreateView, EditView ve DeleteView dahil Düzenleme Views'in bir göz atmalısınız/düzenlemek oluşturmak/a modeli silmek için izin veren bir görünüm yaratmaya çalıştığımız Ancak eğer

. Bunlar için daha fazla bilgiyi https://docs.djangoproject.com/en/1.3/ref/class-based-views/#editing-views numaralı telefondan görebilirsiniz.

hatayı bildirmek nasıl sen https://docs.djangoproject.com/en/1.3/internals/contributing/#reporting-bugs adresinde ayrıntılı yönergeleri takip etmelidir sorusunu cevaplamak için.

+0

Düzenleme/silme sorununa katılıyorum. Düzenleme/silme işlevlerini getirmek için o sayfada bulunan kontroller tarafından izlediğim gibi otomatik bir ekran görüyorum. Tabii ki, genel görünümleri olabildiğince kullanacağım. Neye izin verileceğine dair fikrinizi desteklediğiniz için teşekkür ederim. Django birçok projelerin yolunu giderse kritik bir nokta daha basittir ve daha fazla işlevsellik ortaya çıkacaktır sağlayan bir yeniden yazımını ulaşıldığında daha sonra ek karmaşıklığa ve edecektir. Zaten sınıf tabanlı tabanlı fonksiyondan gittik. Eminim birçok Django zaten bunu aştı. Teşekkürler, Steve – kd4ttc

+0

Yine de bunun bir hata olduğuna ikna olmadı. 'CreateView' 'bir şey için daha uygun olan' DetailView 'kullanmamalısınız. "Get_template_names" için "isinstance" ile test edilmiş olabilirlerdi, bu durumda şablon ismini bulmak için Model örneğini döndürmelisiniz. Bu sayede '_meta' ile bir şey döndürebilir ve şablon ismini alabileceksiniz. Form dışında. Form görünümlerini bununla birlikte kullanmalısınız. –

+0

Bu bir hatadır çünkü bir model olmayan bir _meta örneğine sahip ANY sınıfında gerçekleşecektir. Bir form sınıfı olmak zorunda değildir (FormView kullanmak daha uygundur). –

İlgili konular