Django ModelChoiceField:筛选查询集并将默认值设置为对象

Django ModelChoiceField:筛选查询集并将默认值设置为对象,django,django-forms,Django,Django Forms,我在模型中定义了一个Django表单类,如下所示: class AccountDetailsForm(forms.Form): ... adminuser = forms.ModelChoiceField(queryset=User.objects.all()) 这很好,但它有一些我无法克服的局限性: (1) 我希望根据传递给表单的变量accountid在queryset上使用一个过滤器,如下所示: User.objects.filter(account=accountid)

我在
模型中定义了一个Django表单类,如下所示:

class AccountDetailsForm(forms.Form):
    ...
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())
这很好,但它有一些我无法克服的局限性:

(1) 我希望根据传递给表单的变量
accountid
在queryset上使用一个过滤器,如下所示:

User.objects.filter(account=accountid)
User.objects.filter(account=accountid).filter(primary_user=1)
class AccountDetailsForm(forms.Form):
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())
    account_id = forms.IntegerField()  # or ModelChoiceField if that applies

    def clean(self):
        account_id = self.cleaned_data['account_id']
        self.cleaned_data['adminuser'] = User.objects.filter(account_id=account_id)

    return self.cleaned_data
这在模型中不起作用,因为
accountid
当然不能作为变量传递

因此,
queryset
必须以某种方式在
视图中定义,但据我所知,它是表单类中的必填字段

(2) 我希望默认选择数据库中的对象
AccountDetailsForm
,我可以在
视图中选择该对象,如下所示:

User.objects.filter(account=accountid)
User.objects.filter(account=accountid).filter(primary_user=1)
class AccountDetailsForm(forms.Form):
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())
    account_id = forms.IntegerField()  # or ModelChoiceField if that applies

    def clean(self):
        account_id = self.cleaned_data['account_id']
        self.cleaned_data['adminuser'] = User.objects.filter(account_id=account_id)

    return self.cleaned_data
我已经尝试将adminuser指定为表单中的默认值(这适用于其他标准表单字段,如
CharField
):

但是没有运气

考虑到此处所需的灵活性,我是否应该使用除
modelcoocefield
以外的其他功能


谢谢。

重写init方法并接受新的关键字参数

class AccountDetailsForm(forms.Form):
    ...
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())
    def __init__(self, *args, **kwargs):
        accountid = kwargs.pop('accountid', None)
        super(AccountDetailsForm, self).__init__(*args, **kwargs)

        if accountid:
            self.fields['adminuser'].queryset = User.objects.filter(account=accountid)

form = AccountDetailsForm(accountid=3)
您也可以始终在视图中手动设置选项

form = AccountDetailsForm()
form.fields['adminuser'].queryset = User.objects.filter(account=accountid)

请注意:将字典传递给示例中的表单并不是在设置默认值

实际上,您正在创建一个绑定表单,可能会触发验证和所有这些

要设置默认值


可以替代视图中的字段

yourForm = AccountDetailsForm()

yourForm.fields['accomodation'] = forms.ModelChoiceField(User.objects.filter(account=accountid).filter(primary_user=1))

在Django 2.0中,您可以将对象(
User
在您的情况下)从
视图
传递到
表单
,如下所示(您必须首先从DB检索obj):


它会给你一个默认选择的对象(回答你的2个问题)

这里还没有提到的是方法。此方法专门用于自定义验证

例如,您可以这样做:

User.objects.filter(account=accountid)
User.objects.filter(account=accountid).filter(primary_user=1)
class AccountDetailsForm(forms.Form):
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())
    account_id = forms.IntegerField()  # or ModelChoiceField if that applies

    def clean(self):
        account_id = self.cleaned_data['account_id']
        self.cleaned_data['adminuser'] = User.objects.filter(account_id=account_id)

    return self.cleaned_data
clean()方法在默认的clean方法之后被调用,因此您可以使用self.cleaned_数据(与视图中的form.cleaned_数据相同)并按自己的意愿返回它

更好的是,您可以根据要清理的字段(
def clean\u adminuser
)命名方法,使其更易于阅读

def clean_adminuser(self):
    account_id = self.cleaned_data['account_id']
    return User.objects.filter(account_id=account_id)

此外,如果有任何问题需要处理,您也可以使用此方法进行呼叫。

您好,谢谢您的回复。在视图中设置查询集效果很好。我无法解决的部分是将ModelChoiceField的绑定表单值(而不是默认值)设置为User.objects.filter(account=accountid.filter)(primary_User=1)。谢谢。@jon在表单中?我目前的解决方案就是这里的,但我觉得这不是最有效的方法: