2010-10-15 21 views
11

Tôi có một FormWizard, nơi tôi cần dữ liệu từ biểu mẫu đầu tiên chuyển tới hàm tạo của biểu mẫu thứ hai để tôi có thể tạo biểu mẫu động.Cách chuyển dữ liệu biểu mẫu trước đó tới hàm tạo của DynamicForm trong FormWizard

Tôi có thể lấy dữ liệu của biểu mẫu đầu tiên thông qua process_step của FormWizard.

Tôi tạo các trường của biểu mẫu thứ hai bằng cuộc gọi cơ sở dữ liệu của danh sách trường.

class ConditionWizardDynamicQuestions(forms.Form): 

    def __init__(self, DynamicQuestions=None, *args, **kwargs): 
     super(ConditionWizardDynamicQuestions, self).__init__(*args, **kwargs) 
     questions = Question.objects.filter(MYDATA = DATA_FROM_1STFORM) 
     for q in questions: 
      dynField = FieldFactory(q) 
      self.fields[q.label] = dynField 

Làm thế nào tôi có thể vượt qua DATA_FROM_1STFORM?


đang kết quả của tôi: tôi từ bỏ init dạng, và chuyển nó vào CreateQuestions def. Sau đó sử dụng ghi đè get_form của wizard để thay đổi biểu mẫu sau khi tạo.

class ConditionWizard(SessionFormWizard): 
    def get_form(self, request, storage, step=None, data=None, files=None): 
     form = super(ConditionWizard, self).get_form(request, storage, step, data, files) 
     stepIndex = self.get_step_index(request, storage, step) 
     if stepIndex == 1: 
      form.CreateQuestions(request.session["WizardConditionId"]) 
     if stepIndex == 3: 
      form.fields['hiddenConditionId'].initial = request.session["WizardConditionId"] 
      form.fields['medicationName'].queryset = Medication.objects.filter(condition = request.session["WizardConditionId"]) 
     return form 

Trả lời

5

FormWizard đã chuyển dữ liệu từ mỗi biểu mẫu trước đó sang biểu mẫu tiếp theo. Nếu bạn muốn lấy dữ liệu đó để khởi tạo một lớp (ví dụ, nếu một biểu mẫu có các đối số từ khóa đặc biệt mà nó yêu cầu), một cách để thực hiện nó là lấy truy vấn bằng cách ghi đè get_form trong lớp trình thủ thuật biểu mẫu của bạn. Ví dụ:

class SomeFormWizard(FormWizard): 
    def get_form(self, step, data=None): 
     if step == 1 and data: # change this to whatever step requires 
           # the extra data 
      extra_data = data.get('key_from_querydict') 
      if extra_data: 
       return self.form_list[step](data, 
              keyword_argument=extra_data, 
              prefix=self.prefix_for_step(step),                                    
              initial=self.initial.get(step, None)) 
     # Fallback for the other forms. 
     return self.form_list[step](data, 
            prefix=self.prefix_for_step(step),                                    
            initial=self.initial.get(step, None)) 

Lưu ý rằng bạn cũng có thể ghi đè lên parse_params(self, request, *args, **kwargs) trong FormWizard để truy cập dữ liệu url/yêu cầu, giống như bạn làm trong một cái nhìn, vì vậy nếu bạn có dữ liệu theo yêu cầu (request.user, ví dụ) có nghĩa là sẽ cần thiết cho tất cả các biểu mẫu, có thể tốt hơn để lấy dữ liệu từ đó.

Hy vọng điều này sẽ hữu ích.

+0

Tôi đang gặp sự cố khi truyền dữ liệu từ bước 1 đến bước 3, nhưng giải pháp của bạn hữu ích và sâu sắc. – BozoJoe

+0

Bạn đang gặp phải vấn đề gì? AFAIK nó sẽ cho phép bạn truy cập tất cả các dữ liệu từ tất cả các hình thức trước đó - đó là bước 3 nên có dữ liệu từ bước 1 và bước 2. –

+0

vấn đề của tôi là tôi đã cố gắng sử dụng ban đầu từ trình hướng dẫn và ghi đè biểu mẫu __trong đó__. Tôi chuyển sang sử dụng get_form và thế giới đang trở nên rõ ràng hơn đối với tôi :) – BozoJoe

0

Gần đây tôi đã làm việc với trình hướng dẫn biểu mẫu django và tôi đã giải quyết vấn đề tương tự. Tôi không nghĩ rằng bạn có thể truyền dữ liệu đến init, tuy nhiên, những gì bạn có thể làm, là ghi đè lên init constructor:

next_form = self.form_list[1] 

# let's change the __init__ 
# function which will set the choices :P 
def __init__(self, *args, **kw): 
    super(next_form, self).__init__(*args, **kw) 
    self.fields['availability'].choices = ... 
next_form.__init__ = __init__ 

Đó là khá khó chịu rằng trong python bạn không thể khai báo và gán chức năng trong một lần và phải đặt nó trong không gian tên (trừ khi bạn sử dụng lambdas), nhưng oh tốt.

+0

Tôi không chắc tôi làm theo. Mã này có ghi đè __init__ của FormWizard được phân lớp không? Điều này cho phép tôi lấy dữ liệu từ bước 1 đến bước 2 như thế nào? – BozoJoe

+0

không, nó ghi đè __init__ của biểu mẫu tiếp theo. Lựa chọn như thế nào nó nói self.fields ['sẵn có']. Choice = ..., bây giờ thay vì ... bạn có thể đặt bất kỳ dữ liệu nào bạn muốn vượt qua –

+0

Tôi đã có "next_form" __init__ ghi đè, vì vậy tôi vẫn không ' t xem cách dữ liệu truyền của bạn từ biểu mẫu thuật sĩ trước đó. – BozoJoe

8

Tôi đã giải quyết vấn đề này bằng cách ghi đè get_form_kwargs cho Trình hướng dẫn. Nó thường chỉ trả về một từ điển rỗng mà get_form điền, vì vậy bằng cách ghi đè nó để trả về một từ điển với dữ liệu bạn cần được chuẩn bị sẵn, bạn có thể chuyển các từ kwarg vào init form của bạn.

def get_form_kwargs(self, step=None): 
    kwargs = {} 
    if step == '1': 
     your_data = self.get_cleaned_data_for_step('0')['your_data'] 
     kwargs.update({'your_data': your_data,}) 
    return kwargs 

Sau đó, ở dạng init phương pháp của bạn, bạn chỉ có thể bật kwarg tắt trước khi gọi siêu:

self.your_data = kwargs.pop('client', None) 
3

Override các get_form_kwargs phương pháp của wizard mẫu của bạn trong quan điểm

xem. py

class FormWizard(SessionWizardView): 
    def get_form_kwargs(self, step=None): 
     kwargs = {} 
     if step == '1': 
      step0_form_field = self.get_cleaned_data_for_step('0')['previous_form_field_data'] 
      kwargs.update({'step0_form_field': step0_form_field}) 
     return kwargs 

Ghi đè init của bạn hình thức r bằng cách popping lên các dữ liệu bạn nhận được từ các lĩnh vực trước đó để tạo ra một lĩnh vực năng động.

forms.py

class MyForm(forms.Form): 
    #some fields 

class MyForm1(forms.Form): 
    def __init__(self, *args, **kwargs): 
     extra = kwargs.pop('step0_form_field') 
     super(MyForm1, self).__init__(*args, **kwargs) 

     for i in range(extra): 
      self.fields['name_%s' % i] = forms.CharField() 
Các vấn đề liên quan