django - Dynamic Multiwidget/MultivalueField from Model -


the beginning simple:

class question(models.model):     question_string = models.charfield(max_length=255)     answers = models.charfield(max_length=255) 

answers json of list of strings e.g ['yes', 'no']. number of answers dynamic. challenge me write form model.

current state is:

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 = []         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) 

the problem is: 'the json object must str, not 'nonetype'' in template '{{ field }}'

what wrong?

i found problem. forgot add 'answers' class meta 'fields'.

so example of dynamic multiwidget created model is:

class newquestionform(forms.modelform):      def __init__(self, *args, **kwargs):         # need create right number of fields post         edit_mode = false         if len(args) > 0:             edit_mode = true             answer_fields = 0             counter in range(0, 20):                 answer_key = "answers_" + str(counter)                 if args[0].get(answer_key, none) 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)         # number of fields 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 = []         tdata in json.loads(self.cleaned_data['answers']):             if tdata != '':                 temp_data.append(tdata)         if not temp_data:             raise forms.validationerror('please provide @ least 1 answer.')         return json.dumps(temp_data) 

'clean_answers' has 2 porposes: 1. remove empty answers. 2. failed set required attribute on first widget. check here @ least 1 answer exists

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 = []         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) 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -