在 Class 基于视图中为动态创建的 ModelChoiceField 设置初始值
Set initial value for dynamically created ModelChoiceField in Class Based View
我正在创建一个 Form
,它有一个 ModelChoiceField
。我可以按如下方式设置此字段的值:
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
这很好用,但我似乎无法设置初始值。我尝试了多种方法,例如向 get_initial()
添加初始值:
def get_initial(self):
initial = super(DeviceView, self).get_initial()
initial['user_id'] = self.kwargs['user_id']
default_device = Device.objects.get(user_id=self.kwargs['user_id'], is_validated=True, is_default=True)
initial['devices'] = default_device.id
return initial
但这不起作用。我在 Whosebug 上遇到了多个问题,这些问题实例化了表单并传入了一个初始值,如下所示:
#Get default device
form = DeviceForm(initial={'devices': default_device.id})
但理想情况下我想避免它,因为我试图坚持使用 Django 通用基础视图(看起来像这样,并且据我所知不允许 initial
kwarg我知道):
def get(self, request, user_id, **kwargs):
# Do stuff
form = self.get_form()
return self.render_to_response(self.get_context_data(form=form))
在 get_initial()
中设置设备应该有效,因为 self.get_form_kwargs()
returns:
{'prefix': None, 'initial': {'user_id': u'1', 'devices': 42}}
或者,取决于我应该选择什么:
{'prefix': None, 'initial': {'user_id': u'1', 'devices': <Device: Device object>}}
执行以下操作仍然无法正常工作(基本上与手动 get_form()
相同)。
def get(self, request, user_id, **kwargs):
#Do stuff
form_class = self.get_form_class()
form = form_class(**self.get_form_kwargs())
return self.render_to_response(self.get_context_data(form=form))
在 Form 的构造函数中设置初始值也不起作用:
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
default_device = devices.filter(is_default=True)
self.fields['devices'].initial = default_device # or default_device.id
有谁知道实现这个的方法吗?
您需要使用建议的方式分配 initial
,但它在基于 class 的视图中仍然可用。引用自 django doc:
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
由于您已经覆盖了表单的 __init__
方法,因此在那里设置初始值可能是最简单的方法。
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
default_device = Device.objects.get(user_id=user_id, is_validated=True, is_default=True)
self.fields['devices'].initial = default_device
最后是我在模板中犯了一个愚蠢的错误。该值实际上已在视图中正确设置,但我忘记在模板中设置 checked
值。我以为它只是使用 {{form}}
,但我不是。仅供想知道如何手动设置的人使用:
{% for device in form.devices.field.choices.queryset %}
<input type="radio" name="devices" value="{{ device.pk }}" class="radio-device"
{% ifequal form.devices.value device.pk %}checked{% endifequal %}
/>
{% endfor %}
我正在创建一个 Form
,它有一个 ModelChoiceField
。我可以按如下方式设置此字段的值:
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
这很好用,但我似乎无法设置初始值。我尝试了多种方法,例如向 get_initial()
添加初始值:
def get_initial(self):
initial = super(DeviceView, self).get_initial()
initial['user_id'] = self.kwargs['user_id']
default_device = Device.objects.get(user_id=self.kwargs['user_id'], is_validated=True, is_default=True)
initial['devices'] = default_device.id
return initial
但这不起作用。我在 Whosebug 上遇到了多个问题,这些问题实例化了表单并传入了一个初始值,如下所示:
#Get default device
form = DeviceForm(initial={'devices': default_device.id})
但理想情况下我想避免它,因为我试图坚持使用 Django 通用基础视图(看起来像这样,并且据我所知不允许 initial
kwarg我知道):
def get(self, request, user_id, **kwargs):
# Do stuff
form = self.get_form()
return self.render_to_response(self.get_context_data(form=form))
在 get_initial()
中设置设备应该有效,因为 self.get_form_kwargs()
returns:
{'prefix': None, 'initial': {'user_id': u'1', 'devices': 42}}
或者,取决于我应该选择什么:
{'prefix': None, 'initial': {'user_id': u'1', 'devices': <Device: Device object>}}
执行以下操作仍然无法正常工作(基本上与手动 get_form()
相同)。
def get(self, request, user_id, **kwargs):
#Do stuff
form_class = self.get_form_class()
form = form_class(**self.get_form_kwargs())
return self.render_to_response(self.get_context_data(form=form))
在 Form 的构造函数中设置初始值也不起作用:
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
default_device = devices.filter(is_default=True)
self.fields['devices'].initial = default_device # or default_device.id
有谁知道实现这个的方法吗?
您需要使用建议的方式分配 initial
,但它在基于 class 的视图中仍然可用。引用自 django doc:
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
由于您已经覆盖了表单的 __init__
方法,因此在那里设置初始值可能是最简单的方法。
class DeviceForm(Form):
devices = ModelChoiceField(queryset=None, widget=RadioSelect, empty_label=None)
def __init__(self, *args, **kwargs):
super(DeviceForm, self).__init__(*args, **kwargs)
user_id = kwargs['initial']['user_id']
devices = Device.objects.filter(user_id=user_id, is_validated=True)
self.fields['devices'].queryset = devices
default_device = Device.objects.get(user_id=user_id, is_validated=True, is_default=True)
self.fields['devices'].initial = default_device
最后是我在模板中犯了一个愚蠢的错误。该值实际上已在视图中正确设置,但我忘记在模板中设置 checked
值。我以为它只是使用 {{form}}
,但我不是。仅供想知道如何手动设置的人使用:
{% for device in form.devices.field.choices.queryset %}
<input type="radio" name="devices" value="{{ device.pk }}" class="radio-device"
{% ifequal form.devices.value device.pk %}checked{% endifequal %}
/>
{% endfor %}