2010-04-05 24 views
7

Bir form kümesi oluşturmak için inlineformset_factory kullanmaya çalışıyorum. BenceDjango inlineformset_factory içinde Sorgu Queryset

class Measurement(models.Model): 
    subject = models.ForeignKey(Subject) 
    experiment = models.ForeignKey(Experiment) 
    assay = models.ForeignKey(Assay) 
    values = models.CommaSeparatedIntegerField(blank=True, null=True) 

class Experiment(models.Model): 
    date = models.DateField() 
    notes = models.TextField(max_length = 500, blank=True) 
    subjects= models.ManyToManyField(Subject) 

i var: My modeller olarak tanımlanan

def add_measurement(request, experiment_id): 
    experiment = get_object_or_404(Experiment, pk=experiment_id) 
    MeasurementFormSet = inlineformset_factory(Experiment, Measurement, extra=10, exclude=('experiment')) 
    if request.method == 'POST': 
     formset = MeasurementFormSet(request.POST,instance=experiment) 
     if formset.is_valid(): 
      formset.save() 
      return HttpResponseRedirect(experiment.get_absolute_url()) 
    else: 
     formset = MeasurementFormSet(instance=experiment) 
    return render_to_response("data_entry_form.html", {"formset": formset, "experiment": experiment }, context_instance=RequestContext(request)) 

ama Measurement.subject alanını kısıtlamak istediğiniz Experiment.subjects sorgu kümesi tanımlanan tek denekler için. Bunu yapmanın birkaç farklı yolunu denedim ama bunu başarmanın en iyi yolunun ne olduğu konusunda emin değilim. BaseInlineFormset sınıfını yeni bir queryset ile aşmaya çalıştım, ancak deneme parametresini doğru bir şekilde nasıl geçeceğimi anlayamadım.

(Ben de formset link parametre geçirmek için buraya bir yol olarak bilgi dahil)

Güncelleme cevap :

views.py

def add_measurement(request, experiment_id):  
    experiment = get_object_or_404(Experiment, pk=experiment_id)  
    MeasurementFormSet = inlineformset_factory(Experiment, Measurement, extra=10, can_delete=True, form=MeasurementForm)  
    MeasurementFormSet.form = staticmethod(curry(MeasurementForm, experiment=experiment)) 
    if request.method == 'POST': 
     formset = MeasurementFormSet(request.POST)  
     if formset.is_valid(): 
     formset.save() 
     return HttpResponseRedirect(experiment.get_absolute_url())  
    else: 
     formset = MeasurementFormSet() 
     return render_to_response("data_entry_form.html", {"formset": formset, "experiment": experiment }, context_instance=RequestContext(request)) 

forms.py

class MeasurementForm(ModelForm): 
    class Meta: 
     model = Measurement 
    def __init__(self, *args, **kwargs): 
     experiment = kwargs.pop('experiment') 
     super(MeasurementForm, self).__init__(*args, **kwargs) 
     self.fields["subject"].queryset = Subject.objects.filter(experiment=experiment) 
+0

Python'da bir köri() 'yi daha önce hiç duymadım, kesinlikle yerleşik değil. EDIT: ... Ahh .. Sadece bağlantılı yazıyı fark ettim: django.utils'ten .functional import curry – Rich

+0

Bu hala Django 1.5'te çalışıyor mu? Aşağıdaki hatayı alıyorum: __init __() beklenmedik bir anahtar kelime argümanı var 'empty_permitted' – Puzzled79

cevap

3

(düzenleme: kod bloklarını düzgün okumadı, sorununuzu çözmeniz gerekir):

Sana ihtiyacım inanıyoruz: http://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield

Forms.py:

class MeasurementForm(ModelForm): 
subject = forms.ModelChoiceField(queryset = Expirement.objects.all()) 
class Meta: 
    model = Measurement 

Views.py:

inlineformset_factory(
    Experiment, Measurement, extra=10, 
    exclude=('experiment'), form=MeasurementForm 
) 

Cilt formu parametresi kullanılarak yapılır formset için.

+0

Bunu denedim ama çok şansım yok. Filtre ve önek öğelerinin amacı nedir? – Dave

+0

Cevabımı dün düzelttim, modelchoicefield bir çözüm için gerekli malzemelere sahip olmalı. –

+0

Kodumu değiştirdim (sorudaki eke bakın) ancak şimdi hata kaydediliyor. Hata şu anda "Atama yapılamıyor" <Ölçüm: Ölçme nesnesi> ":" Ölçüm "ifadesi" Deneme "örneği olmalıdır." – Dave

1

Aynı konuyla ilgiliydim (olası olası değerleri olan satır içi biçimleri başlat) ve Güncelleştirilen yanıt harika çalışıyor. Bunun için teşekkürler. Her neyse, daha iyi yapılabilecek bir şey var sanırım, ama nasıl yapılacağı konusunda hiçbir fikrim yok. Yerine aynı alanda aynı Sorgu Kümesi kullanmanın bu satırda o her seferinde yeniden hesaplar: o çözümde yeni sayısının her inlineform içinde veritabanını isabet olmasıdır

self.fields["subject"].queryset = Subject.objects.filter(experiment=experiment) 

tam bu konuda Am I veya kaputun arkasında biraz tembel-django büyüsü var mı? Eğer haklıysam, DB'ye (olası yüzlerce) isabetten nasıl kaçınabilirim? Selamlar, Pedro

+0

DB'deki isabetlerden kaçınmak için, queryset süzgecini kullanmanız yeterlidir. ŁukaszKorzybski'nin [trick] kullanımı (http://stackoverflow.com/a/2108902/623735) - 'eğer değilse (kend, '_queryset'): – hobs