如何将 ManyToManyField 中的数据放入 MultipleChoiceField 中的选项

How to put data from ManyToManyField to choices in MultipleChoiceField

我有一个表格:

*# dialogues.forms*

class CreateConferenceForm(forms.Form):
    ...
    participants = forms.MultipleChoiceField(choices=?)
    ...

而且我需要输入 choices 参数而不是“?”此模型中来自好友字段的数据:

*# persons.models*

class Person(User):
    ...
    friends = models.ManyToManyField(
        'self',
        related_name='+',
    ) 
    ...

我该怎么做?

你可以试试这个

class CreateConferenceForm(forms.Form):
    """
    """
    participants = forms.MultipleChoiceField()

    def __init__(self, *args, **kwargs):
        # Pass the request in the form.
        self.request = kwargs.pop('request', None) 

        super(CreateConferenceForm, self).__init__(*args, **kwargs)

        if self.request:
            pass

        # Get the person object according to you need. Whether from request or hard-coded.
        person = Person.objects.filter().first()
        friend_choices = [(dct['id'], dct['id']) for dct in (person.friends.values('id'))]
        self.fields['participants'].choices = friend_choices

As friend 字段对象也是Person as MamyToMany with self。你也可以试试这个

class CreateConferenceForm(forms.Form):
    """
    """
    # Replace second 'id' in values_list('id', 'id') with the field in you person model.
    participants = forms.MultipleChoiceField(choices=list(Person.objects.filter().values_list('id', 'id')))

如果您要使用表单创建会议模型的实例,您应该考虑使用 Django's ModelForm,它旨在用于创建和编辑模型实例。

在任何一种情况下,您都可以使用 ModelMultipleChoiceField 来达到您的目的,这只是一个由查询集支持的 MultipleChoiceField 以供其选择。您可以在标准 FormModelForm.

中使用此字段

要根据请求自定义选项,您可以在视图中设置查询集。

例如:

forms.py

class CreateConferenceForm(forms.Form):
    # An initial queryset is required, this is overwritten in the view
    participants = forms.ModelMultipleChoiceField(Person.objects.all())

views.py

def new_conference(request):
    data = request.POST if request.method == 'POST' else None

    conference_form = CreateConferenceForm(data=data)
    conference_form.fields['participants'].queryset = my_person.friends.all()

    if data:
        if conference_form.is_valid():
            # etc

    return render...

请注意,在表单上调用 is_valid 之前设置查询集很重要,因为查询集用于验证,并且在将表单传递给模板之前设置查询集,因为查询集用于生成显示的选项。