在POST时,构造函数中的Django ModelMultipleChoiceField更新查询集失败

时间:2011-01-07 15:35:42

标签: django django-forms http-post django-queryset

我一直在从StackOverflow上的各种问题中提取出来,试图弄清楚如何在表单中使用ModelMultipleChoiceFields。我几乎有一个工作表单,允许用户选择语言来翻译文章。我创建了一个表单,它将SourceArticle作为第一个构造函数参数,并使用它来为表单的languages字段指定查询集。

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'对象有   没有属性'language'

我认为这与Django中表单的工作方式有关,但我很新。而不是接受SourceArticle作为构造函数中的第一个参数,而是放置QueryDict。我假设这包含来自请求的POST参数。如何修改我的代码以允许它捕获所选语言?

以下是我的观点的副本,如果它可以帮助您了解我如何使用该表单。

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

1 个答案:

答案 0 :(得分: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...