web-dev-qa-db-fra.com

Django ModelChoiceField: filtrage de l'ensemble de requêtes et définition de la valeur par défaut en tant qu'objet

J'ai une classe Django Form définie comme ça dans Models:

class AccountDetailsForm(forms.Form):
    ...
    adminuser = forms.ModelChoiceField(queryset=User.objects.all())

Cela fonctionne bien, mais il a certaines limitations que je n'arrive pas à contourner:

(1) Je voudrais utiliser un filtre sur l'ensemble de requêtes, basé sur une variable accountid passée au formulaire, comme ceci:

User.objects.filter(account=accountid)

Cela ne peut pas fonctionner dans le modèle car accountid ne peut pas être passé en tant que variable, bien sûr.

Il s'ensuit que le queryset doit en quelque sorte être défini dans le Views, mais autant que je sache, c'est un champ obligatoire dans la classe Form.

(2) Je voudrais faire le choix par défaut de AccountDetailsForm un objet dans la base de données, que je peux sélectionner dans le Views comme ceci:

User.objects.filter(account=accountid).filter(primary_user=1)

J'ai essayé de spécifier l'administrateur en tant que valeur par défaut dans le formulaire (qui fonctionne avec d'autres champs de formulaire standard, comme 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})

Mais pas de chance.

Dois-je utiliser autre chose que ModelChoiceField étant donné la flexibilité dont j'ai besoin ici?

Merci.

55
eli

Substituez la méthode init et acceptez un nouvel argument de mot clé

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)

Vous pouvez également toujours définir les choix manuellement dans la vue.

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

Soyez averti: vous ne définissez pas des valeurs par défaut en passant un dictionnaire à un formulaire comme dans votre exemple.

Vous créez en fait un formulaire lié, ce qui peut déclencher la validation et tout ce jazz.

Pour définir les valeurs par défaut, tilisez l'argument des initiales.

form = AccountDetailsForm(initial={'adminuser':'3'})
101

Vous pouvez remplacer le champ dans la vue

yourForm = AccountDetailsForm()

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

Dans Django 2.0 vous pouvez passer un objet (User dans votre cas) du view au form comme ceci (vous devez récupérer obj de la DB en premier):

form = AccountDetailsForm(initial={'adminuser': adminuser})

Il vous donnera un objet sélectionné par défaut (répond à votre 2) question)

0
techkuz