2017-04-06 2 views
0

から始まりは単純です:ダイナミックMultiwidget/MultivalueFieldモデル

class Question(models.Model): 
    question_string = models.CharField(max_length=255) 
    answers = models.CharField(max_length=255) 

答えは、[ 'はい'、 'いいえ']の文字列例えばリストのJSONです。回答の数は動的です。 私の挑戦は、このモデルのためのフォームを書くことです。

現在の状態は以下のとおりです。

class NewQuestionForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     super(NewQuestionForm, self).__init__(*args, **kwargs) 

     if self.instance: 
      self.fields['answers'] = AnswerField(num_widgets=len(json.loads(self.instance.answers))) 

    class Meta: 
     model = Question 
     fields = ['question'] 
     widgets = { 
      'question': forms.TextInput(attrs={'class': "form-control"}) 
     } 


class AnswerField(forms.MultiValueField): 
    def __init__(self, num_widgets, *args, **kwargs): 
     list_fields = [] 
     list_widgets = [] 
     for garb in range(0, num_widgets): 
      field = forms.CharField() 
      list_fields.append(field) 
      list_widgets.append(field.widget) 

     self.widget = AnswerWidget(widgets=list_widgets) 
     super(AnswerField, self).__init__(fields=list_fields, *args, **kwargs) 

    def compress(self, data_list): 
     return json.dumps(data_list) 

class AnswerWidget(forms.MultiWidget): 

    def decompress(self, value): 
     return json.loads(value) 

問題がある:私は得る{{フィールド}} '

は何か 'で、テンプレートに' NoneType '' JSONオブジェクトは、ないのをstrされなければなりません'違う?

答えて

0

問題が見つかりました。私はクラスのメタフィールドに「回答」を追加するのを忘れていました。

だから、モデルから作成されたダイナミックMultiwidgetの私の例は次のとおりです。1.空の答えを削除します。

class NewQuestionForm(forms.ModelForm): 

    def __init__(self, *args, **kwargs): 
     # need this to create right number of fields from POST 
     edit_mode = False 
     if len(args) > 0: 
      edit_mode = True 
      answer_fields = 0 
      for counter in range(0, 20): 
       answer_key = "answers_" + str(counter) 
       if args[0].get(answer_key, None) is not None: 
        answer_fields = counter + 1 
       else: 
        break 
     super(NewQuestionForm, self).__init__(*args, **kwargs) 
     if edit_mode: 
      self.fields['answers'] = AnswerField(num_widgets=answer_fields, required=False) 
     # get number of fields from DB 
     elif 'instance' in kwargs: 
      self.fields['answers'] = AnswerField(num_widgets=len(json.loads(self.instance.answers)), required=False) 
     else: 
      self.fields['answers'] = AnswerField(num_widgets=1, required=False) 

    class Meta: 
     model = Question 
     fields = ['question', 'answers'] 
     widgets = { 
      'question': forms.TextInput(attrs={'class': "form-control"}) 
     } 

    def clean_answers(self): 
     temp_data = [] 
     for tdata in json.loads(self.cleaned_data['answers']): 
      if tdata != '': 
       temp_data.append(tdata) 
     if not temp_data: 
      raise forms.ValidationError('Please provide at least 1 answer.') 
     return json.dumps(temp_data) 

'clean_answersは' 2 porposesを持っています。 2.最初のウィジェットで必須属性を設定できませんでした。だから私はここで少なくとも1つの答えが存在することを確認する

class AnswerWidget(forms.MultiWidget): 

    def decompress(self, value): 
     if value: 
      return json.loads(value) 
     else: 
      return [''] 


class AnswerField(forms.MultiValueField): 
    def __init__(self, num_widgets, *args, **kwargs): 
     list_fields = [] 
     list_widgets = [] 
     for loop_counter in range(0, num_widgets): 
      list_fields.append(forms.CharField()) 
      list_widgets.append(forms.TextInput(attrs={'class': "form-control"})) 
     self.widget = AnswerWidget(widgets=list_widgets) 
     super(AnswerField, self).__init__(fields=list_fields, *args, **kwargs) 

    def compress(self, data_list): 
     return json.dumps(data_list)