我一直在从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))
答案 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...