2011-06-25 10 views
7

同じ基本クラスから継承したモデルのセットのフォームを処理するために汎用のCreateViewクラスを使用しようとしています。Django:パラメトリッククラスベースのビュー

class BaseContent(models.Model): 
    ... 

class XContent(BaseContent): 
    ... 

class YContent(BaseContent): 
    ... 

DRYを維持するために、BaseContentのすべての継承クラスを処理するCreateViewクラスを1つ定義します。

そのビューのURLパターンがある。このような

url(r'^content/add/(?P<model_name>\w+)/$', ContentCreateView.as_view(), name='content_add') 

何かが動作するはずです:

class ContentCreateView(CreateView): 
    template_name = 'content_form.html' 

    def get_model(self, request): 
     # 'content' is the name of the application; model_name is 'xcontent', 'ycontent', ... 
     return ContentType.objects.get_by_natural_key('content', self.model_name) 

しかし、私はこの例外を取得しています:

ContentCreateView is missing a queryset. Define ContentCreateView.model, ContentCreateView.queryset, or override ContentCreateView.get_object(). 

この提案はしませんmodelquerysetなどのクラス属性を設定するつもりはないので、保持しているようですモデル・フォームを動的に生成する。 get_objectを上書きすることは、オブジェクトの作成には関係しないようです。

get_queryset()をオーバーライドしようとしましたが、この方法ではrequestパラメータを受け入れることも、URLパターンに由来するself.model_nameにアクセスすることもできません。

URLから渡されたパラメータに基づいてCreateViewで動的フォームを使用するにはどうすればよいですか?

ありがとうございました。

+0

:あなたは、as_view(で定義されている発送方法、)(django.views.generic.base)をオーバーライドするために、このようなものが必要get_queryset()メソッドの中で.requestとself.model_name。その考えをしなかった。 – bmihelac

+1

はい、CreateViewの祖先であるViewクラスは、URLからのkwargsをインスタンス変数として設定します。 'self.model_name'は' self.request'が他のmixinから来ているので、 'get_queryset()'にアクセスできません。私がモデル名を 'get'パラメータとして渡すと、私は自分が望むことをすることができますが、うまくいかないでしょう。クラスベースのビューとドキュメントの不足で継承とミックスインが編成される方法は、クラスのメソッドと属性をトレースすることを非常に複雑にします。 – omat

+1

それぞれのモデルのフォームクラスを作成し、 'ModelFormMixin'のget_form_classメソッドをオーバーライドして、要求パラメータに基づいてビューの関連フォームを取得することはできませんか?最後の手段として – vimukthi

答えて

1

あなたが呼び出されているURLに応じて、あなたのごurls.pyからmodel属性を設定できます。

url(r'^content/add/x/$', 
    ContentCreateView.as_view(model=XContent), name='x_content_add'), 
url(r'^content/add/y/$', 
    ContentCreateView.as_view(model=YContent), name='y_content_add') 

私は自分自身を少し繰り返しているとして、それは完璧ではない認めるが、それゆえ、あなたが持つことの利点を持っていますモデルに応じて、同じビューの異なる名前を使用します。それ以外に、form_classをオーバーライドして同様のことをすることもできます。

+0

as_view()は引数を受け入れていないようです。あなたが提案した方法は: 'as_view()はちょうど1つの引数(与えられた2)'をとります。私はこのようにurlパターンを修正しました: 'url(r 'add/x/$'、ContentCreateView.as_view()、{'queryset':XContent.objects。all()}) 'と呼びますが、kwargはクラスインスタンスに渡されていないようです:' ContentCreateViewにはクエリーセットがありません。 ' – omat

+0

申し訳ありませんが私のせいで、もちろん、あなたはそれをkwargsとして渡す必要があります。 –

+0

更新していただきありがとうございます。すぐに文書化されることを願っていますが、多重継承の複数のレベルでは容易ではありません。 – omat

1

この問題はしばしば解決されましたが解決策が見つかりました。私はその要求とMODEL_NAMEはインスタンス変数として設定することだろうと思うので、あなたは自分でし

class ContentCreateView(CreateView):  
    def dispatch(self, request, *args, **kwargs): 
     for app in ['foo', 'bar']: 
      model = models.get_model(app, kwargs['modelname']) 
      if model: 
       self.model = model 
       break 

     return super(GenericEdit, self).dispatch(request, *args, **kwargs) 
    ... 
    ...