2009-08-21 35 views
18

Tôi có một bộ mẫu mà tôi cần phải chuyển từ khóa ban đầu vào (để có một số giá trị ban đầu trong bộ định dạng, chẳng hạn như ngày được đặt thành hôm nay). Theo như tôi có thể nói, đối số queryset (mặc định là YourModel.objects.all()) sẽ ghi đè khả năng này cho các biểu mẫu trống ban đầu được tạo ra. Tôi đã chỉ định queryset là: YourModel.objects.none(), ngăn chặn nó điền vào formset với các mục từ cơ sở dữ liệu, nhưng tôi vẫn không thể tìm ra cách để vượt qua ban đầu một cách hiệu quả. Tôi có cần phải phân lớp một phương thức từ ModelForm?Chuyển ban đầu vào ModelFormSet của Django

+1

Bạn muốn thay đổi một trường hợp cụ thể của mô hình, nhưng bạn không muốn hiển thị các giá trị hiện tại của nó và thay vào đó hiển thị các giá trị ban đầu khác nhau? –

Trả lời

0

Một giải pháp đơn giản có thể là bạn chuyển biểu mẫu mở rộng một biểu mẫu() đến một bộ định dạng (chứ không phải là modelformset).

Bằng cách đó bạn có thể đặt giá trị ban đầu trong biểu mẫu.

+1

Bạn có thể giải thích về điều này không? Tôi không chắc tôi hiểu ý bạn là gì. – Vince

2

Nó vẫn còn có thể vượt qua ban đầu để một 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'}]) 

Nếu đây không phải là nội dung sau, bạn có thể giải thích câu hỏi của mình hơn không.

EDIT:

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

Theo mặc định, các mẫu biểu mẫu của Django tự cư trú với kết quả của yourmodel.objects.all(). Điều này có thể được đảo ngược với queryset = yourmodel.objects.none(), nhưng điều này vẫn không cho phép các giá trị ban đầu. Một cái gì đó về việc có bộ truy vấn và từ khóa ban đầu được đặt làm cho việc này không hoạt động. – Vince

+0

Làm thế nào nó không hoạt động, nó không làm gì? Bằng cách sử dụng mã cập nhật, tôi nhận được một formset từ một queryset trống và các giá trị ban đầu được điền vào. – Gerry

+0

Vâng .. đây là cách để đi. Tôi đồng ý. – simplyharsh

8

Bạn đang đi qua một queryset trống để ModelFormset.

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

thực sự là cách để đạt được những gì bạn muốn. Nó có ý nghĩa để vượt qua một queryset trống, các giá trị ban đầu khác sẽ ghi đè lên giá trị cơ sở dữ liệu của mô hình. Và nếu tôi cho rằng, bạn đang chuyển một bộ truy vấn không trống, và vẫn muốn các biểu mẫu bổ sung của bạn được lấp đầy sẽ là các giá trị ban đầu, bạn có thể ghi đè lên 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 

Lưu ý: initial là danh sách các dicts. Mong muốn của nó để có các mục trong danh sách chính xác bằng số lượng thêm.

+1

Một thủ thuật khiến tôi ở đây là bạn phải đặt số lượng lớn hơn hoặc bằng số lượng phần tử trong dữ liệu ban đầu của mình. Tôi biết đó là câu trả lời của bạn, nhưng tôi nghĩ nó rất đáng chú ý. – Bacon

1

Bạn có thể thay đổi dữ liệu ban đầu sau đó.

Ví dụ:

# 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

Khi tôi thử điều đó (với formset_factory), tôi nhận được đối tượng ''str' không có thuộc tính 'initial'' Tôi có thể làm gì sai? – LukasKawerau

+0

@LukasKawerau: hãy kiểm tra những gì 'form.fields' trả về. Mã này có thể cần chỉnh sửa. – vdboor

+0

@LukasKawerau, trong python 2.7 (ít nhất) lặp lại trên từ điển chỉ cung cấp các khóa không dữ liệu – maazza

1

Trong Django 1.4 quy tắc đã thay đổi: số lượng chữ cái đầu được hiển thị tương ứng với thông số "thừa". https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values

Trong trường hợp của tôi số lượng các thông số ban đầu thay đổi tự động, vì vậy tôi thấy cách sau:

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) 

cung cấp, ExampleModelFormSet được dựa trên MyBaseFormSet

0

Cách đơn giản làm thế nào để vượt qua ban đầu dữ liệu có cùng số lượng biểu mẫu bổ sung:

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

Cách sử dụng i n lần xem:

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

Affter hai ngày thấy điều này: 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

Cách tốt nhất mà tôi đã tìm thấy để làm điều này là chỉ cần tự điều chỉnh "thêm" thuộc tính sau khi khởi tạo đối tượng formset của. Điều này đã được thử nghiệm và hoạt động ở Django 1.9.

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

Điều này sẽ tạo ra 3 biểu mẫu (2 được chuẩn bị trước và 1 trống).

Nếu bạn muốn một cái gì đó năng động hơn (ví dụ initial là một var tính ở một nơi khác), bạn có thể làm một cái gì đó như thế này:

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

Hy vọng rằng sẽ giúp.

Các vấn đề liên quan