2009-08-21 87 views
18

我有一個模型formset,需要將關鍵字initial初始化爲(在formset中包含一些初始值,例如設置爲今天的日期)。據我所知,queryset參數(默認爲YourModel.objects.all())將覆蓋此功能以創建初始空表單。我將查詢集指定爲:YourModel.objects.none(),它阻止它使用數據庫中的條目填充表單集,但我仍然無法弄清楚如何有效地傳遞初始值。我是否需要從ModelForm中繼承一個方法?將初始值傳遞給Django的ModelFormSet

+1

您想更改模型的特定實例,但不想顯示其現有值,而是顯示不同的初始值? –

回答

0

一個簡單的解決方案可能是您將一個將modelform()擴展到formset(而不是modelformset)的窗體。

這樣你可以在窗體中設置初始值。

+1

你能詳細說明一下嗎?我不確定我明白你的意思。 – Vince

2

但仍可以通過最初的ModelFormSet。

from django.forms.models import modelformset_factory 
from example.models import ExampleModel 

ExampleModelFormSet = modelformset_factory(ExampleModel) 
formset = ExampleModelFormSet(initial=[{'name': 'Some Name'}, 
             {'name': 'Another Name'}]) 

如果這不是你以後的問題,你能解釋一下你的問題嗎?

編輯:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2) 
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), 
           initial=[{'name': 'Some Name'}, 
             {'name': 'Another Name'}]) 
+0

默認情況下,Django的模型表單使用yourmodel.objects.all()的結果填充自己。這可以通過queryset = yourmodel.objects.none()來反轉,但這仍然不允許初始值。有關查詢集和初始關鍵字設置的事情使這不起作用。 – Vince

+0

它不起作用,它不做什麼?通過使用更新後的代碼,我從一個空的查詢集中獲取一個formset並填入初始值。 – Gerry

+0

是的..這是要走的路。我同意。 – simplyharsh

8

你傳遞一個空的查詢集來ModelFormset。

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=2) 
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), 
          initial=[{'name': 'Some Name'}, 
            {'name': 'Another Name'}]) 

這確實是實現你想要的方式。傳遞一個空的查詢集合是有意義的,否則初始值將覆蓋模型的數據庫值。

如果我想,你傳遞一個非空的查詢集,但又希望你的額外表單被填充將初始值,你可以覆蓋Formset

from django.forms.models import modelformset_factory 
ExampleFormset = modelformset_factory(OpenIDProfile, extra=3) 

class myFormset(ExampleFormset): 

    def _construct_form(self, i, **kwargs): 
     """ 
     Instantiates and returns the i-th form instance in a formset. 
     """ 
     if self.is_bound and i < self.initial_form_count(): 
      pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name) 
      pk = self.data[pk_key] 
      pk_field = self.model._meta.pk 
      pk = pk_field.get_db_prep_lookup('exact', pk) 
      if isinstance(pk, list): 
       pk = pk[0] 
      kwargs['instance'] = self._existing_object(pk) 
     if i < self.initial_form_count() and not kwargs.get('instance'): 
      kwargs['instance'] = self.get_queryset()[i] 

     defaults = {'auto_id': self.auto_id, 'prefix': self.add_prefix(i)} 
     if self.data or self.files: 
      defaults['data'] = self.data 
      defaults['files'] = self.files 
     # Check to confirm we are not overwriting the database value. 
     if not i in range(self.initial_form_count()) and self.initial: 
      try: 
       defaults['initial'] = self.initial[i - self.initial_form_count()] 
      except IndexError: 
       pass 
     # Allow extra forms to be empty. 
     if i >= self.initial_form_count(): 
      defaults['empty_permitted'] = True 
     defaults.update(kwargs) 
     form = self.form(**defaults) 
     self.add_fields(form, i)   
     return form 

注意:initial是字典列表。它希望列表中的項目完全等於額外的數量。

+1

讓我在這裏的一個訣竅是,您必須設置額外的大於或等於您的初始數據中元素的數量。我知道這是你的答案,但我認爲這值得強調。 – Bacon

1

之後您可以更改初始數據。

例如:

# Construct the FormSet class 
ExampleFormSet = modelformset_factory(ParentModel, ChildModel) 

# Set the initial data 
initial_data = {'field1': 1} 
for form in ExampleFormSet.extra_forms: 
    for field in form.fields: 
     field.initial = initial_data[field.name] 
+0

當我嘗試(與formset_factory),我得到''str'對象沒有屬性'initial'' 我可能做錯了什麼? – LukasKawerau

+0

@LukasKawerau:請檢查一下'form.fields'返回的內容。此代碼可能需要更正。 – vdboor

+0

@LukasKawerau,在Python 2.7(至少)在字典上迭代只會獲得密鑰而不是數據 – maazza

1

在Django 1.4中,規則發生了變化:要顯示的首字母的數量對應於「額外」參數。 https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

在我的情況下初始參數的數量是動態變化的,所以 我發現下面的方法:

initial=[{'name': 'Some Name'},{'name': 'Another Name'}] 
formset = ExampleModelFormSet(queryset=ExampleModel.objects.none(), 
         initial=initial, extra=len(initial)) 


class MyBaseFormSet(BaseModelFormSet): 
    def __init__(self, *args, **kwargs): 
     self.extra = kwargs.pop('extra', self.extra) 
     super(MyBaseFormSet, self).__init__(*args, **kwargs) 

提供,ExampleModelFormSet基於MyBaseFormSet

0

簡單的方法如何通過初始具有相同計數的額外形式的數據:

MyModelFormSet = lambda *a, **kw: modelformset_factory(MyModel, extra=kw.pop('extra', 1))(*a, **kw) 

用法i n個視點:

initial=[{'name': 'Some Name'},{'name': 'Another Name'} 
formset = MyModelFormSet(queryset=MyModel.objects.none(), initial, extra=len(initial))}) 
0

Affter2天發現這一點:http://streamhacker.com/2010/03/01/django-model-formsets/

def custom_field_callback(field): 
    return field.formfield(required=False) 

FormSet = modelformset_factory(model, formfield_callback=custom_field_callback) 

def custom_field_callback(field): 
    if field.name == 'optional': 
     return field.formfield(required=False) 
    elif field.name == 'text': 
     return field.formfield(widget=Textarea) 
    elif field.name == 'integer': 
     return IntegerField() 
    else: 
     return field.formfield() 
5

我發現要做到這一點,最好的辦法是隻手動調整初始化後該formset對象的「額外」的屬性。這已經過測試,並在Django 1.9中運行。

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1) 
formset = ExampleModelFormSet(initial=[{'name': 'Some Name'}, 
             {'name': 'Another Name'}]) 
formset.extra = 3 

這將吐出3種形式(2個預填充和1個空白)。

如果你想要的東西更動態(例如initial是別的地方計算的變量),你可以做這樣的事情:

ExampleModelFormSet = modelformset_factory(ExampleModel, extra=1) 
formset = ExampleModelFormSet(initial=initial) 
formset.extra += len(initial) 

希望有所幫助。

相關問題