2011-01-07 38 views
1

StackOverflowに関するさまざまな質問から、フォーム内でModelMultipleChoiceFieldsを操作する方法を理解しようとしています。私はほとんどの場合、ユーザーが記事を翻訳する言語を選択できるようにする作業形式を持っています。私はSourceArticleを最初のコンストラクタ引数として受け取り、それを使って自分のフォームのlanguagesフィールドのクエリセットを指定します。コンストラクタ内のDjango ModelMultipleChoiceField更新クエリセットがPOSTで失敗する

class AddTargetLanguagesForm(forms.Form): 
    def __init__(self, article=None, *args, **kwargs): 
    super(AddTargetLanguagesForm, self).__init__(*args, **kwargs) 
    self.fields['languages'].queryset = Language.objects.exclude(
         Q(id = article.language.id) | 
         Q(id__in=[o.id for o in article.get_target_languages()]) | 
         Q(code="templates")) 

    languages = forms.ModelMultipleChoiceField(_("Languages")) 

それは私のモデルオブジェクトのいずれかに直接関係はないので、私のAddTargetLanguagesFormは、ModelFormに基づいていないことに注意してください。

フォームを初めてレンダリングするとき、(a)ソース言語ではなく、(b)まだ選択されていない、(c)特別な "テンプレート "言語。しかし、私は自分のフォームを投稿しようとすると、私は次のエラーを取得:

AttributeError: 'QueryDict' object has no attribute 'language'

を、私は、これはフォームはジャンゴでどのように動作するかに関係していることを前提としていますが、私はかなり新しいです。コンストラクタの最初のパラメータとしてSourceArticleを受け入れるのではなく、代わりにQueryDictが配置されます。私はこれに要求からのPOST paramsが含まれていると仮定します。選択した言語をキャプチャできるようにするには、コードを変更する必要がありますか?

フォームをどのように使用しているかを確認するのに役立つ場合は、ここに私のビューのコピーがあります。

@login_required 
def add_target_languages(request, aid, template_name="wt_articles/add_target_languages.html"): 
    """ 
    Adds one or more target language translations to a source article. 
    """ 
    content_dict = {} 

    # Fetch the article 
    no_match = False 

    sa_set = SourceArticle.objects.filter(id=aid) 
    if len(sa_set) < 1: 
     no_match = True 
     content_dict['no_match'] = no_match 
    else: 
     article = sa_set[0] 
     content_dict['article'] = article 

     if request.method == "POST": 
      target_language_form = AddTargetLanguagesForm(request.POST) 

      if target_language_form.is_valid(): 
       languages = target_language_form.cleaned_data['languages'] 

       article.add_target_languages(languages) 
       return HttpResponseRedirect('/articles/list') 
     else: 
      target_language_form = AddTargetLanguagesForm(article) 

     content_dict['target_language_form'] = target_language_form 
    return render_to_response(template_name, content_dict, 
           context_instance=RequestContext(request)) 

答えて

3

この行はあなたの問題です:

target_language_form = AddTargetLanguagesForm(request.POST) 

POSTからフォームをインスタンス化するための標準的な方法ですが、トラブルは、あなたがAddTargetLanguagesForm.__init__のメソッドシグネチャ書き換えられたことであること:

def __init__(self, article=None, *args, **kwargs): 

であり、最初の位置引数(自動selfの後)はarticleです。あなたインスタンス化を変更することもできますが、私はこれを行うことを好む:

def __init__(self, *args, **kwargs): 
    article = kwargs.pop('article', None) 
    super(AddTargetLanguagesForm, self).__init__(*args, **kwargs) 
    if article is not None: 
     ...etc... 
+0

素敵なソリューションを、あなたの助けのための –

+0

感謝をkwargs.pop。私は 'AddTargetLanguagesForm .__ init__'の署名を保持するように変更し、' article'値を 'target_language_form = AddTargetLanguagesForm(article、request.POST)'のように渡すことにしました。 'kwargs.pop'を使って試してみましたが、これらの変更の結果としてフォームをレンダリングするときにエラーが発生しました。さらにトラブルシューティングする代わりに、メソッドのシグネチャを変更することになりました。 –

関連する問題