2009-11-08 17 views
17

El caso particular que tengo es la siguiente:¿Cómo pasar el parámetro inicial a la instancia de ModelForm de django?

que tienen un modelo de transacción, con los campos: from, to (ambos son ForeignKey s a auth.User modelo) y amount. En mi forma, me gustaría presentar al usuario 2 campos a rellenar: amount y from (to se establecerá automáticamente se para el usuario actual en una función de vista).

control por defecto para presentar un ForeignKey es un select-box. Pero lo que quiero llegar, es limitar las opciones a los miembros de QuerySet user.peers solamente (para que la gente sólo se pueden registrar las transacciones con sus pares y no se inundan con todos los usuarios del sistema).

He intentado cambiar el ModelForm a algo como esto:

class AddTransaction(forms.ModelForm): 
    from = ModelChoiceField(user.peers) 
    amount = forms.CharField(label = 'How much?') 

    class Meta: 
    model = models.Transaction 

Pero parece que tengo que pasar el conjunto de consultas de opciones para ModelChoiceField aquí - en donde no tengo un acceso a la web request.user objeto.

¿Cómo puedo limitar las opciones en un formulario para los dependientes del usuario?

Respuesta

29

utilizar el siguiente método (esperemos que sea lo suficientemente clara):

class BackupForm(ModelForm): 
    """Form for adding and editing backups.""" 

    def __init__(self, *args, **kwargs): 
     systemid = kwargs.pop('systemid') 
     super(BackupForm, self).__init__(*args, **kwargs) 
     self.fields['units'] = forms.ModelMultipleChoiceField(
       required=False, 
       queryset=Unit.objects.filter(system__id=systemid), 
       widget=forms.SelectMultiple(attrs={'title': _("Add unit")})) 

    class Meta: 
     model = Backup 
     exclude = ('system',) 

crear formularios de esta manera:

form_backup = BackupForm(request.POST, 
         instance=Backup, 
         systemid=system.id) 
form_backup = BackupForm(initial=form_backup_defaults, 
         systemid=system.id) 

Espero que ayude! Avíseme si necesita que le explique más en profundidad.

+0

¡Muchas gracias! Esto realmente ayudó. – kender

+4

Desde el interior de la clase Form, puede acceder a la instancia del Modelo a través de 'self.instance'. Recuerde que la instancia estará en blanco cuando agregue/cree un nuevo objeto. – JCotton

+2

Un poco más simple es capturar systemid como un argumento normal en su __init __() mientras pasa ** kwargs directamente: 'def __init __ (self, systemid, * args, ** kwargs): super (BackupForm, self) .__ init __ (* args, ** kwargs) ' – JCotton

2

En http://www.djangobook.com/en/2.0/chapter07/, la sección Configuración de los valores iniciales describe cómo utilizar el parámetro initial a la Form constructor. También puede hacer cosas extra en el método de su derivada Form__init__.

+0

pasando los datos iniciales establecería mi cuadro de selección en el valor especificado, no limitaría las opciones, ni modificaría la validación, que obtendría con la configuración de QuerySet en la definición de ModelForm. – kender

+0

Puede inspeccionar el parámetro inicial (o algún otro parámetro) en su constructor y establecer los límites en consecuencia? –

6

me encontré con este problema también, y esto fue mi solución:

class ChangeEmailForm(forms.ModelForm): 
    def __init__(self, user, *args, **kwargs): 
     self.user = user 
     super(ChangeEmailForm, self).__init__(*args, **kwargs) 
     self.fields['email'].initial = user.email 

    class Meta: 
     model = User 
     fields = ('email',) 

    def save(self, commit=True): 
     self.user.email = self.cleaned_data['email'] 
     if commit: 
      self.user.save() 
     return self.user 
0

Pasar el usuario en el __init__ de la forma, y ​​luego llamar a super(…). Luego configure self.fields['from'].queryset en user.peers

Cuestiones relacionadas