2011-02-02 1 views
22

Il costruttore per forms.ModelChoiceField richiede un set di query. Non conosco il set di query fino a quando non si verifica la richiesta. Distillata:Come impostare dinamicamente il queryset di un model.ModelChoiceField su una sottoclasse forms.Form

# models.py 
class Bar(models.model): 
    text = models.TextField() 

class Foo(models.Model): 
    name = models.CharField() 
    bar = models.ForeignKey(Bar) 

# forms.py 
class FooForm(forms.Form): 
    name = forms.CharField() 
    text = forms.CharField(widget=forms.TextArea) 

    bar = forms.ModelChoiceField(queryset='??????') 

Quello che sto facendo attualmente:

# forms.py 

def get_foo_form_class(bars_queryset): 
    class FooForm(forms.Form): 
     name = forms.CharField() 
     text = forms.CharField(widget=forms.TextArea) 

     bar = forms.ModelChoiceField(queryset=bars_queryset) 

    return FooForm 

posso quindi chiamare nella vista utilizzando gli argomenti analizzati fuori l'url con un urlconf per costruire il set di query e ottenere la classe. Questo sembra il modo sbagliato per farlo. C'è un modo stabilito per farlo in django?

risposta

50

Ignora il metodo __init__ del modulo e imposta lì il set di parametri.

class FooForm(forms.Form): 
    bar = forms.ModelChoiceField(queryset=Bar.objects.none()) 

    def __init__(self, *args, **kwargs): 
     qs = kwargs.pop('bars') 
     super(FooForm, self).__init__(*args, **kwargs) 
     self.fields['bar'].queryset = qs 
11

È anche possibile farlo nella visualizzazione prima di presentare il modulo nel modello. Io uso questo e lo trovo più flessibile in caso si ri-utilizzare il modulo in altre viste e la necessità di cambiare il set di query ogni volta:

from assets.models import Asset 
location_id = '123456' 
edit_form = AsssetSelectForm(request.POST or None, instance=selected_asset) 
edit_form.fields["asset"].queryset = Asset.objects.filter(location_id=location_id) 

Ho anche impostare il set di query di default a nessuno nel forms.py:

class AsssetSelectForm(forms.Form): 
    asset = forms.ModelChoiceField(queryset=Asset.objects.none())