我在Models
中定义了一个Django Form类:
class AccountDetailsForm(forms.Form):
...
adminuser = forms.ModelChoiceField(queryset=User.objects.all())
这样可行,但它有一些限制我似乎无法解决:
(1)我想在查询集上使用过滤器,基于传递给表单的变量accountid
,如下所示:
User.objects.filter(account=accountid)
这在模型中不起作用,因为accountid
当然不能作为变量传递。
因此queryset
必须以某种方式在Views
中定义,但据我所知,它是Form类中的必填字段。
(2)我想在数据库中默认选择AccountDetailsForm
一个对象,我可以在Views
中选择这样的对象:
User.objects.filter(account=accountid).filter(primary_user=1)
我尝试将adminuser指定为表单中的默认值(适用于其他标准表单字段,如CharField
):
adminuser = User.objects.filter(account=accountid).filter(primary_user=1)
...
form = AccountDetailsForm({'adminuser': adminuser})
return render_to_response('accounts/edit/accountdetails.html',
{'form': form, 'account':account})
但没有运气。
我是否应该使用ModelChoiceField
之外的其他内容,因为我需要灵活性?
感谢。
答案 0 :(得分:100)
覆盖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)
警告:您不通过将字典传递到示例中的表单来设置默认值。
您实际上正在创建一个绑定表单,可能会触发验证和所有爵士乐。
设置默认值use the initials argument.
form = AccountDetailsForm(initial={'adminuser':'3'})
答案 1 :(得分:6)
您可以覆盖视图中的字段
yourForm = AccountDetailsForm()
yourForm.fields['accomodation'] = forms.ModelChoiceField(User.objects.filter(account=accountid).filter(primary_user=1))
答案 2 :(得分:1)
Form.clean()方法尚未在此处提及。此方法专门用于自定义验证。
对于您的示例,您可以执行以下操作:
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_data(与视图中的form.cleaned_data相同)并根据需要返回它。
更好的是,您可以根据要清理的字段(def clean_adminuser
)命名方法,并使其更易于阅读。
def clean_adminuser(self):
account_id = self.cleaned_data['account_id']
return User.objects.filter(account_id=account_id)
如果您要处理任何问题,也可以使用此方法致电Form.add_error()。
答案 3 :(得分:0)
在Django 2.0中,您可以像这样将对象(在您的情况下为User
)从view
传递到form
(您必须首先从数据库检索obj):>
form = AccountDetailsForm(initial={'adminuser': adminuser})
它将为您提供一个默认的选定对象(回答您的2个问题)