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
Post a Comment