62 votes

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

J'ai un Django classe de Forme définie aime cela, en Models:

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

Ceci fonctionne bien, mais il a quelques limitations, je n'arrive pas à contourner:

(1) je voudrais utiliser un filtre sur le queryset, basé sur une variable accountid passé pour le formulaire, comme ceci:

User.objects.filter(account=accountid)

Cela ne peut pas fonctionner sur le modèle, car accountid ne peut pas être passé comme une variable, bien sûr.

Il s'ensuit que l' queryset doit être en quelque sorte défini dans l' Views, mais aussi loin que je peux voir, c'est un champ requis dans le Formulaire de classe.

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

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

J'ai essayé en précisant le adminuser comme valeur par défaut dans le formulaire (qui fonctionne avec les autres types de champs de formulaire, 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 de l' ModelChoiceField compte tenu de la souplesse-je ici?

Merci.

111voto

Yuji 'Tomita' Tomita Points 46106

Remplacer la méthode d'initialisation et d'accepter un nouvel argument 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 toujours définir le choix manuellement dans la vue ainsi.

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

Soyez averti: vous êtes à la non définition des valeurs par défaut par le passage d'un dictionnaire à un formulaire, comme dans votre exemple.

Vous créez en fait une Forme Liée, provoquant la validation et tout ce jazz.

Pour définir les valeurs par défaut, utiliser les initiales de l'argument.

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

6voto

Vous pouvez remplacer le champ dans la vue

 yourForm = AccountDetailsForm()

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X