Django - UpdateView ModelForm 在查询集字段上设置初始值

Posted

技术标签:

【中文标题】Django - UpdateView ModelForm 在查询集字段上设置初始值【英文标题】:Django - UpdateView ModelForm setting initial value on queryset field 【发布时间】:2018-11-19 15:22:24 【问题描述】:

我正在尝试更新其中一个值来自查询集的模型对象。对象创建完美 - 它使用传递给模板的查询集,然后在 POST 上将其保存到对象中。

我的问题:名为 parent_jury 的字段在模板中显示为空的选择字段。它不包含原始字段值。如何将初始字段值设置为对象中的内容并允许用户从查询集中的其他值中进行选择?

但现在我正在尝试update 对象。代码如下:

#forms.py

def __init__(self, *args, **kwargs):
    pk = kwargs.pop('pk')
    yr = kwargs.pop('yr')
    jr = kwargs.pop('jr') 

    self.customer_id = pk
    self.court_year_id = yr
    super().__init__(*args, **kwargs)

    # This prints the correct value for the the object I'm trying to update
    print("pr: ", Jury.objects.get(
        jury_id=jr).parent_jury)  

    # This is my latest attempt to get the initial value (or any value) to 
    # be presented in the modelform/template.
    self.fields['parent_jury'].initial = Jury.objects.get(
        jury_id=jr).parent_jury

除了上面的代码,我还尝试使用以下代码提取正确的 __init__() 值:

#forms.py (other attempts)

self.fields['parent_jury'] = forms.ChoiceField(
    required = False,
    choices = Jury.objects.filter(
        customer_id=pk).filter(
        court_year_id = yr),
    initial = Juriy.objects.get(
        jury_id=jr).parent_jury)

我的模板反映了我的 createview 模板(可能导致部分问题)。

#template.html

<tr><td>Parent Jury:</td><td><select name="parent_jury">
    % for item in form.parent_jury.field.queryset %
        <option value=" item "> item </option>
    % endfor %
</select></td></tr>

我确实遇到了this,但它使用了一个单独的过滤器类——我希望在__init__ 中处理。

很有可能我的问题实际上出在模板中 - 我遇到了 this,但仍宁愿管理 ModelForm 中交付的内容(以及如何交付)。

后续问题:

或者...是否可以将初始值与其他所有内容一起传递到模板中,然后将其编码到模板中?

更新我

我几乎想通了 - 这是 forms.py __ini__() 将正确的 choices 传递给模板:

def __init__(self, *args, **kwargs):
    pk = kwargs.pop('pk')
    yr = kwargs.pop('yr')
    jr = kwargs.pop('jr') 

    self.customer_id = pk
    self.court_year_id = yr
    super().__init__(*args, **kwargs)
    print("pr: ", Juriy.objects.get(
        jury_id=jr).parent_jury)

    choices = list(Jury.objects.filter(
        client_id = pk).filter(
        court_year_id = yr).values_list('jury_name', 'jury_name'))

    print("choices: ", choices)
    self.fields['parent_jury'] = forms.ChoiceField(
        choices = choices,
        )

.values_list() 中,我已经包含'jury_name' 两次以使列表项正常工作。下面的模板只有一个值会引发错误:not enough values to unpack (expected 2, got 1)。通过两个可以解决这个问题。

在我拥有的模板中:

<tr><td>Parent Jury:</td><td><select name="parent_jury">
    % for item in form.parent_jury %
        <option value=" item "> item </option>
    % endfor %
</select></td></tr>

#output
Thingy1
Thingy1
Thingy2
Thingy2
Thingy3
Thingy3

如您所见,现在的问题是表单上的select/option 字段实际上复制了键条目。每个键在下拉菜单中显示两次。

我还在模板底部运行了以下代码,结果正确:

% for item in form.parent_jurisdiction %
    item
% endfor %

#output
Thingy1
Thingy2
Thingy3

我该如何解决这个问题?

更新二

我在下面的回答是错误的...尽管删除 item 标签实际上会更改选项以仅包含一组选项-它不会在 POST 中传递-而是我在发布报告:

parent_jury         '<option value='

所以,越来越近了 - 视图是正确的,但选择的选项没有被传回。

更新 III

为模板找到了正确的构造...答案已更新:

可以在here找到模板的原始 SO 答案。

【问题讨论】:

【参考方案1】:

最后一块在模板中。

原代码如下:

<option value=" item "> item </option>

这导致value 元素和label 元素都包含在选项列表中。由于两者具有相同的值,因此它们(thingy 或另一个 thingy1)在 POST 中具有相同的结果。这个select/option/iteration 的构造可以在here 找到。

#update code
<tr><td>Parent Jurisdiction:</td><td><select name="parent_jury">
    % for val, item in form.fields.parent_jury.choices %
            <option value=" item "% if form.fileds.parent_jury.value == val% selected% endif %> item </option>
    % endfor %
</select></td></tr>

作为后续说明,在选项中使用查询集对象需要两者:

# passing queryset to select/option
<tr><td>Parent Jury:</td><td><select name="parent_jury">
    % for item in form.parent_jury.field.queryset %
        <option value=" item "> item </option>
    % endfor %
</select></td></tr>

【讨论】:

以上是关于Django - UpdateView ModelForm 在查询集字段上设置初始值的主要内容,如果未能解决你的问题,请参考以下文章

Django UpdateView 错过查询集

UpdateView FileField不删除以前的文件Django python

Django 1.8 UpdateView 生成 405 错误和空白模板

Django:仅更新UpdateView中已更改的字段

进阶剖析django通用类UpdateView(2张图)

使用基于类的 UpdateView 在 Django 中更新用户模型