7

機能的なWebサイトが、チュートリアルの一般的なビューとどれほど迅速に連携できるかに感銘を受けました。また、フォーム処理のワークフローも優れています。ModelFormヘルパークラスを使用して、作成したモデルからフォームを作成しましたが、非常に多くの機能が一緒になっているのを見てうれしく思いました。一般的なlist_detail.object_detailを使用したとき、表示できるのが個別のフィールドだけであることに失望しました。ModelFormクラスにレンダリング用の情報が含まれていることを知っていたので、汎用ビューでModelFormを使用したいと思いました。

私はstackoverflowについていくつかの方向性を得るために周りに尋ねていました、そしていくつかのポスターからの答えとコメントに感謝します。これを機能させる方法を理解しましたが、DetailViewにバグがあります。このソリューションには回避策が含まれています。

汎用ビューでModelViewを使用し、すべてのフィールドを取得して自動的にレンダリングするには、次のように機能します。

プロジェクトを作成し、その中にアプリケーション入院患者を作成します。

あなたが持っている場合

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

できます。クラスベースのジェネリックビューを使用するための手順は、https: //docs.djangoproject.com/en/1.3/topics/class-based-views/にあります。手順はかなり明確です。物事を機能させるための鍵は、get_objectを再定義することです。「追加作業の実行」セクションのドキュメントでは、これを行う方法、元のバージョンのget_objectを呼び出してから、追加作業を行う手順について説明しています。私が気付いたのは、returnオブジェクトがModelFormオブジェクトである可能性があるということです。get_objectが返すオブジェクトは、レンダリングでテンプレートに直接入ります。取得した入院患者オブジェクトを取得し、それをInpatientFormで実行することにより、フォームとしてビューに渡して、それ自体をレンダリングできます。

バグについて:DetailViewのバグは、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'オブジェクトに属性'app_label'>がない状態で終了することです。_metaオブジェクトが定義されていると結論付けます。問題は、ModelFormでクラスMetaが定義されていることだと思います。そのメタには、おそらく期待されるフィールドが設定されていません。回避策は、get_template_namesを書き直して、正しいテンプレートを返すことです。

私はDjangoとPythonを初めて使用します。私が以前に尋ねた以下の質問に対する貢献者の回答とコメントに感謝します。( list_detail.object_listからlist_detail.object_detailへのリンクの配置、object_detailでの フォームの使用、Djangoでの独自のジェネリックビューのローリング )

バグを報告するにはどうすればよいですか?

4

1 に答える 1

2

あなたは正しいと私は信じています。これは、ModelFormとModelsの両方に_meta属性があるという事実に起因するバグです。get_object()この同じバグは、_meta属性を含むオブジェクトが返されるたびに発生します。

get_objectModelインスタンスを返す必要はありません。これは、のソースを調べてそのDetailViewdocstringを読むことで確認できます。

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

doc文字列は、self.get_object()をオーバーライドすることですべてのオブジェクトがサポートされることを明示的に示していることに注意してください。

裏付けとなるもう1つの証拠は、このバグ自体が発生した場所からのものget_template_names methodですSingleObjectTemplateResponseMixin

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

このコードをもう一度見ると、コメント自体に「問題のオブジェクトがモデルの場合」と書かれています。このコメントから、オブジェクトは必ずしもモデルである必要はないことが推測できます。

ただし、誰かがモデルを編集/作成/削除できるビューを作成しようとしている場合は、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に詳述されているガイドラインに従う必要があります。

于 2011-07-04T17:12:26.770 に答える