2011-01-07 1 views
1

Я пытаюсь выяснить, как работать с ModelMultipleChoiceFields в форме, из разных вопросов в StackOverflow. У меня почти есть рабочая форма, которая позволяет пользователям выбирать языки для перевода статьи. Я создал форму, которая принимает SourceArticle в качестве первого аргумента конструктора и использует его для указания набора запросов для поля languages моей формы.Django ModelMultipleChoiceField updatesetset в конструкторе не работает в 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, потому что он не имеет прямого отношения к какой-либо из моих объектов модели.

Когда я визуализую форму в первый раз, она правильно предоставляет мне языки, которые (а) не являются исходным языком, (b) еще не выбраны и (c) не являются специальными " шаблоны ". Однако, когда я пытаюсь опубликовать мою форму, я получаю следующее сообщение об ошибке:

AttributeError: 'QueryDict' object has no attribute '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)) 

ответ

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

красивым решения, kwargs.pop –

+0

Спасибо за вашу помощь. Я решил изменить, чтобы сохранить подпись 'AddTargetLanguagesForm .__ init__' и передать значение' article' следующим образом: 'target_language_form = AddTargetLanguagesForm (article, request.POST)'. Я попытался использовать 'kwargs.pop', но я получил ошибку при рендеринге моей формы в результате этих изменений. Вместо дальнейшего устранения неполадок я в конечном итоге изменил подпись метода. –