问题
I have a Django Form class defined likes this in Models
:
class AccountDetailsForm(forms.Form):
...
adminuser = forms.ModelChoiceField(queryset=User.objects.all())
This works OK, but it has some limitations I can't seem to work around:
(1) I would like to use a filter on the queryset, based on a variable accountid
passed to the form, like this:
User.objects.filter(account=accountid)
This can't work in the model because accountid
can't be passed as a variable, of course.
It follows that the queryset
must somehow be defined in the Views
, but as far as I can see it's a required field in the Form class.
(2) I would like to make the default choice of AccountDetailsForm
an object in the database, which I can select in the Views
like this:
User.objects.filter(account=accountid).filter(primary_user=1)
I've tried specifying the adminuser as a default value in the form, (which works with other standard form fields, like 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})
But no luck.
Should I be using something other than ModelChoiceField
given the flexibility I need here?
Thanks.
回答1:
Override the init method and accept a new keyword argument
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)
You can always just set the choices manually in the view as well.
form = AccountDetailsForm()
form.fields['adminuser'].queryset = User.objects.filter(account=accountid)
Be warned: you are not setting default values by passing in a dictionary to a form like in your example.
You are actually creating a Bound Form, potentially triggering validation and all that jazz.
To set defaults, use the initials argument.
form = AccountDetailsForm(initial={'adminuser':'3'})
回答2:
You can override the field in the view
yourForm = AccountDetailsForm()
yourForm.fields['accomodation'] = forms.ModelChoiceField(User.objects.filter(account=accountid).filter(primary_user=1))
回答3:
In Django 2.0 you can pass object (User
in your case) from the view
to the form
like this (you have to retrieve obj from the DB first):
form = AccountDetailsForm(initial={'adminuser': adminuser})
It will give you a default selected object (answers your 2) question)
来源:https://stackoverflow.com/questions/5329586/django-modelchoicefield-filtering-query-set-and-setting-default-value-as-an-obj