更改 django.forms.models.ModelChoiceIterator

问题描述 投票:0回答:1

ModelForm 中我的字段之一(django.forms.models.ModelChoiceIterator)的选择变量包含 3 项。 在某些情况下,我只想使用其中一个(“列表”中的第一个)作为实际的 HTML。

这是 Django Python 代码的一部分:

类 MyForm(ModelForm):

def __init__(self, *args, user=None, **kwargs):
  choices = self.fields['xxx'].choices
  qs = choices.queryset
  qs = qs[:1]
  ...
  ...

  self.fields['xxx'] = forms.ChoiceField(
    label="xxx",
      widget=forms.Select(
        attrs={
            'class': 'form-select' }
     ),

  self.fields['xxx'].choices  = choices
  self.fields['xxx'].choices.queryset  = qs

  class Meta:
    ...
    model = MyModel
    fields = ('xxx')

    ...

这会引发错误:“列表”对象没有属性“查询集””,并且显然,选择的大小和内容不会改变。
choices 是 django.forms.models.ModelChoiceIterator 的实例 如何减少将在 HTML 中显示的 choices 中的项目数量?

python django modelform
1个回答
0
投票

这要看情况。如果您想限制字段的选择并在验证期间应用此限制,您可以尝试如下操作:

from django.forms import ModelForm


class MyForm(ModelForm):
    def __init__(self, *kargs, **kwargs):
        super().__init__(*kargs, **kwargs)
        self.fields["xxx"].queryset = self.fields["xxx"].queryset.filter(
            pk=self.fields["xxx"].queryset.first().pk
        )

在这种情况下不能使用切片查询集,因为稍后在验证期间无法过滤切片查询集。

另一方面,如果您想限制字段的选择而不影响验证,您可以将字段的迭代器设置为

ModelChoiceIterator
的自定义子类,然后自己在
MyForm
中实例化该字段。

from django.forms import ModelForm
from django.forms.models import ModelChoiceField, ModelChoiceIterator


class FirstItemModelChoiceIterator(ModelChoiceIterator):
    def __init__(self, field):
        self.field = field
        self.queryset = field.queryset[:1]


class FirstItemModelChoiceField(ModelChoiceField):
    iterator = FirstItemModelChoiceIterator


class MyForm(ModelForm):
    xxx = FirstItemModelChoiceField(queryset=...)

上面的代码不处理空查询集。

在 Django 4.2.7 上测试。

© www.soinside.com 2019 - 2024. All rights reserved.