2013-03-04 13 views
6

'daki her form için ForeignKey seçeneklerini sorgulamasını önlerim Django uygulamam için bir csv içe aktarma formu yapıyorum ve doğrulamak amacıyla içe aktarılan satırları bir ModelFormSet içinde görüntülemek istiyorum.Django, ModelFormSet

Bu nedenle, csv'den satırları okuyan ve ModelFormSet(queryset=an_empty_queryset, initial={data_from_the_csv})'u yazdıran ilgili ModelAdmin görünümüne bir görünüm ekledim.

problem modeli, bir veritabanı sorgusu ModelChoiceField 'ın seçenekleri doldurmak amacıyla verilir formset her formda her alanın ForeignKey alanlar aracılığı ile için üç diğer modellere başvuran olmasıdır.

Django neden formu önbelleğe almıyor (birkaç kez kullanıldığı gibi) veya bunu yapmak için zaten bir yol var mı?

+1

django1.5 modeli bellek önbelleği bulunur. – danihp

+1

Haklısınız (https://docs.djangoproject.com/en/1.5/releases/1.5/#caching-of-related-model-instances), ancak maalesef bu sorunu etkilemez. – jnns

+0

Bu sorunu çözmek için küçük bir hack yaptım: http://stackoverflow.com/a/43105646/8450 –

cevap

11

Django form kümeleri, form oluşturma işleminin tüm ayrıntılarını yalnızca form nesnelerine aktarır ve tek tek form örnekleri diğerlerinin farkında değildir, dolayısıyla her birinin kendi seçimleri için sorgulaması beklenmedik bir durum değildir.

önbelleğe alma aynı zamanda yan etkileri üzerindeki istenmeyen - örneğin, formun __init__ fonksiyonu önbelleğe form amacı hatalı hale aldığı initial verilerine bağlı olabilir.

Sorgu sayısını azaltmanın en iyi yolu, seçim sorgularını bir kez almak ve bunları oluşturucudaki form sınıflarınıza iletmektir. Bu, özel bir ModelForm ve özel bir ModelFormSet tanımlanmasını gerektirecektir.

doğrudan seçimler kabul eden bir kurucu gerekir şekliniz:

from django.forms.models import ModelForm 

class MyForm(ModelForm): 
    def __init__(self, my_field_choices=None, *args, **kwargs): 
     super(MyForm, self).__init__(*args, **kwargs) 
     self.fields['my_field'].choices = my_field_choices 

Ve onlar inşa ediyoruz gibi Formset Sorgu kümelerini çalıştırmak ve formlar içine geçmesi için bir yöntem geçersiz kılmak gerekir:

from django.forms.models import BaseModelFormSet 

class MyFormSet(BaseModelFormSet): 
    def _construct_forms(self): 
     # instantiate all the forms and put them in self.forms 
     self.forms = [] 

     # Define each of your choices querysets 
     my_field_choices = Model.object.filter(...) 

     #Add your querysets to a dict to pass to the form 
     form_defaults = {'my_field_choices': my_field_choices, } 

     for i in xrange(min(self.total_form_count(), self.absolute_max)): 
      self.forms.append(self._construct_form(i, **form_defaults)) 

(bu nasıl olacağı içine bakmak the Django source bakınız)

+0

Sorumu cevaplamak için zaman ayırdığınız için teşekkür ederiz. Çözümün aklımda olan şeydi, ama şimdi bunun gitmenin yolu olduğunu biliyorum! – jnns

+0

Bu sorunu aynı sorun için kullandım, ancak kaydederken "atama yapılamıyor" u'7 '":" Stop.city "bir" Şehir "örneği olmalıdır." Stop, City fk olan ModelForm (formset oluşturmak için kullanılır). Çevrenizden geçmek için herhangi bir yolu var mı ?, bu şekilde daha fazla gitmek için fazla yük var gibi görünüyor. – mariodev

+0

@mariodev, Sorunun açıklanmasına/izlenmesine yardımcı olmak için daha fazla kod göndermeniz gerekebilir. Muhtemelen bu adaleti yapmak için yorumlarda yeterli yer yoktur, bu yüzden muhtemelen kendi sorusu için daha uygundur. –