0

The thing is quite obvious to my mind, still I can get it working.

Previously I tried to get the filtered model instances from MultipleModelChoiceField by overriding the __init__ method and it worked as expected. Now I need to get only pk from those instances and I decided to do it in MultipleChoiceField. I try to do it the following way but do not succeed:

class AnswerForm(forms.Form):
    answers = forms.MultipleChoiceField(
        choices = [answer.pk for answer in Answer.objects.all()],
        widget = forms.CheckboxSelectMultiple,
    )

    def __init__(self, *args, **kwargs):
        q_pk = kwargs.pop('q_pk')
        super(AnswerForm, self).__init__(*args, **kwargs)
        self.fields['answers'].choices = [answer.pk for answer in Answer.objects.filter(question__pk=q_pk)]
chem1st
  • 1,624
  • 1
  • 16
  • 22
  • I'm stuck at about the same thing myself and I'm going through this SO post at the moment; http://stackoverflow.com/questions/488036/django-modelmultiplechoicefield-doesnt-select-initial-choices which I think can be helpful, see the attached article in the selected answer – user1749431 Oct 25 '15 at 12:51
  • Note that [answer.pk for answer in Answer.objects.all()] goes through all the objects in class Answer, if you only want to pk one or some fields in class Answer then you might need to delete the other fieldnames, delete kwargs["fieldname"], for the other fields that have been imported into the form through all() in the forms _init_, see the link in the previous comment. – user1749431 Oct 25 '15 at 12:58

2 Answers2

3

In a nutshell: don't do this, stick with ModelMultipleChoiceField.

It obviously won't work because choices expects a list of tuples. Taking that in account, [answer.pk for answer in Answer.objects.filter(question__pk=q_pk)] can be rewritten like Answer.objects.filter(question__pk=q_pk).values_list('pk', 'someotherfield'), which brings you back to what ModelMultipleChoiceField does.

Ivan
  • 5,803
  • 2
  • 29
  • 46
1

Many thanks to Ivan for his pointing me at using ModelChoiceField. It is my inattention, since I only now figured out that I need some other model fields (except pk) to be passed to the form as well.

In that case the best way, that I found to get the model primary key as a value of a chosen input(s) is to get the entire models from form first and then iterate them to get the desired field value as follows:

forms.py

class AnswerForm(forms.Form):
    answer = forms.ModelMultipleChoiceField(
        queryset = Answer.objects.all(),
        widget = forms.CheckboxSelectMultiple,
    )

    def __init__(self, *args, **kwargs):
        q_pk = kwargs.pop('q_pk', None)
        super(AnswerForm, self).__init__(*args, **kwargs)
        self.fields['answer'].queryset = Answer.objects.filter(question__pk=q_pk)

views.py

checked = [answer.pk for answer in form.cleaned_data['answer']]
chem1st
  • 1,624
  • 1
  • 16
  • 22