从视图中,如何将自定义“选择”传递到表单的 ChoiceField?
Posted
技术标签:
【中文标题】从视图中,如何将自定义“选择”传递到表单的 ChoiceField?【英文标题】:From the View, how do I pass custom "choices" into a form's ChoiceField? 【发布时间】:2018-05-01 23:17:57 【问题描述】:根据 Django 文档,ChoiceField 接受 an iterable of two tuples, "or a callable that returns such an iterable" 用作字段的选择。
我在表单中定义了ChoiceFields
:
class PairRequestForm(forms.Form):
favorite_choices = forms.ChoiceField(choices=[], widget=Radioselect, required=False)
这是我试图传递自定义选择元组的视图:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_initial(self):
requester_obj = Profile.objects.get(user__username=self.request.user)
accepter_obj = Profile.objects.get(user__username=self.kwargs.get("username"))
# `get_favorites()` is the object's method which returns a tuple.
favorites_set = requester_obj.get_favorites()
initial = super(PairRequestView, self).get_initial()
initial['favorite_choices'] = favorites_set
return initial
在我的models.py
中,这是上面使用的返回元组的方法:
def get_favorites(self):
return (('a', self.fave1), ('b', self.fave2), ('c', self.fave3))
据我了解,如果我想预先填充表单,我会通过覆盖get_initial()
来传递数据。我尝试使用可调用设置表单favorite_choices
的初始数据。可调用的是favorites_set
。
使用当前代码,我得到一个错误'tuple' object is not callable
如何使用自己的选择预先填充 RadioSelect ChoiceField?
编辑:我也试过设置initial['favorite_choices'].choices = favorites_set
【问题讨论】:
【参考方案1】:get_initial
方法用于填充表单字段的初始值。不要设置可用的choices
或修改你的字段属性。
要成功地将您的选择从视图传递到表单,您需要在视图中实现get_form_kwargs
方法:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_form_kwargs(self):
"""Passing the `choices` from your view to the form __init__ method"""
kwargs = super().get_form_kwargs()
# Here you can pass additional kwargs arguments to the form.
kwargs['favorite_choices'] = [('choice_value', 'choice_label')]
return kwargs
在您的表单中,从 __init__
方法中的 kwargs 参数中获取选项并在字段中设置选项:
class PairRequestForm(forms.Form):
favorite_choices = forms.ChoiceField(choices=[], widget=RadioSelect, required=False)
def __init__(self, *args, **kwargs):
"""Populating the choices of the favorite_choices field using the favorites_choices kwargs"""
favorites_choices = kwargs.pop('favorite_choices')
super().__init__(*args, **kwargs)
self.fields['favorite_choices'].choices = favorites_choices
瞧!
【讨论】:
在编辑self.fields[].choices
之前调用super().__init__()
是否有特殊原因?
如果您之前不调用基本__init__
,您将不会定义任何fields
属性。 fields
属性在此处的BaseForm
init 方法中定义:github.com/django/django/blob/master/django/forms/forms.py#L95【参考方案2】:
另一种简单的方法是:
class PairRequestView(FormView):
form_class = PairRequestForm
def get_form(self, *args, **kwargs):
requester_obj = Profile.objects.get(user__username=self.request.user)
favorites_set = requester_obj.get_favorites()
form = super().get_form(*args, **kwargs)
form.fields['favorite_choices'].choices = favorites_set
return form
【讨论】:
【参考方案3】:您应该将选择封装在表单构造函数的适当参数中。假设您有一个“组”下拉菜单,并且您想传递“组选择”:
class CreateAccountForm(forms.Form):
def __init__(self, groupChoices_, *args, **kwargs):
super(CreateAccountForm, self).__init__(*args, **kwargs)
self.fields['group'].choices = groupChoices_
group = forms.ChoiceField()
在您看来,始终使用 groupChoices_ 作为第一个参数,例如:
groupChoices = [
(2, 'A'),
(4, 'B'),
]
form = CreateAccountForm(groupChoices, request_.POST)
不用担心kwargs
太可怕了!
【讨论】:
这不能回答问题,因为 OP 使用 FormView以上是关于从视图中,如何将自定义“选择”传递到表单的 ChoiceField?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 drupal 6 中的自定义字段将自定义版本的节点/添加表单放在视图中?
将自定义道具传递给 TypeScript 中的 Redux 表单字段