在基于类的视图

时间:2016-01-07 16:35:04

标签: python django django-models django-forms django-class-based-views

我创建的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

但这并不奏效。我在StackOverflow上遇到了多个问题,它们实例化表单并传入一个初始值,如下所示:

#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()会返回:

{'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

有谁知道如何实现这个目标?

3 个答案:

答案 0 :(得分:1)

您需要使用建议的方式来指定initial,但它仍然可以在基于类的视图中使用。引自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})

答案 1 :(得分:0)

由于您已经覆盖了表单的__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

答案 2 :(得分:0)

最后,我在模板中犯了一个愚蠢的错误。实际上在视图中正确设置了值,但我忘记在模板中设置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 %}