11

charfield と choicefield を持つ multivaluefield があります。選択肢を Choicefield コンストラクターに渡す必要がありますが、それをカスタムの複数値フィールドに渡そうとすると__init__()、予期しないキーワード引数 'choices' が含まれているというエラーが発生します。

残りのコードが機能することはわかっています。なぜなら、choices キーワード引数を__init__and super から削除すると、multivaluefield が正しく表示されますが、選択肢がないからです。

これは、カスタムの複数値フィールドをセットアップする方法です。

class InputAndChoice(object):
    def __init__(self, text_val='', choice_val=''):
        self.text_val=text_val
        self.choice_val=choice_val

class InputAndChoiceWidget(widgets.MultiWidget):
    def __init__(self, attrs=None):
        widget = (widgets.TextInput(),
                  widgets.Select()
                 )
        super(InputAndChoiceWidget, self).__init__(widget, attrs=attrs)

    def decompress(self,value):
        if value:
            return [value.text_val, value.choice_val]
        return [None, None]


class InputAndChoiceField(forms.MultiValueField):
    widget = InputAndChoiceWidget

    def __init__(self, required=True, widget=None, label=None, initial=None,
                 help_text=None, choices=None):
        field = (
                 fields.CharField(),
                 fields.ChoiceField(choices=choices),
                 )
        super(InputAndChoiceField, self).__init__(fields=field, widget=widget, 
              label=label, initial=initial, help_text=help_text, choices=choices)

そして、私はそれを次のように呼びます:

input_and_choice = InputAndChoiceField(choices=[(1,'first'),(2,'second')])

では、選択肢を ChoiceField フィールドに渡すにはどうすればよいでしょうか。

編集:

私はstefanwの提案を試みましたが、まだうまくいきません。私は logging.debug を使用して、init の最後に InputAndChoiceField の内容を出力しました。self.fields[1].choices には上記のように正しい値が含まれていますが、ブラウザには選択肢が表示されません。

4

5 に答える 5

4

私はこれとまったく同じ問題に遭遇し、次のように解決しました:

class InputAndChoiceWidget(widgets.MultiWidget):
    def __init__(self,*args,**kwargs):
        myChoices = kwargs.pop("choices")
        widgets = (
            widgets.TextInput(),
            widgets.Select(choices=myChoices)
        )
        super(InputAndChoiceWidget, self).__init__(widgets,*args,**kwargs)

class InputAndChoiceField(forms.MultiValueField):
    widget = InputAndChoiceWidget

    def __init__(self,*args,**kwargs):
        # you could also use some fn to return the choices;
        # the point is, they get set dynamically 
        myChoices = kwargs.pop("choices",[("default","default choice")])
        fields = (
            fields.CharField(),
            fields.ChoiceField(choices=myChoices),
        )
        super(InputAndChoiceField,self).__init__(fields,*args,**kwargs)
        # here's where the choices get set:
        self.widget = InputAndChoiceWidget(choices=myChoices)

ウィジェットのコンストラクターに「choices」kwargを追加します。次に、フィールドが作成された後、コンストラクターを明示的に呼び出します。

于 2012-04-05T06:43:50.187 に答える
2

ModelChoiceFieldは技術的には ですChoiceFieldChoiceFieldが、実際にはの実装を使用していません。だから、ここに私がそれを使用する方法があります。

class ChoiceInputMultiWidget(MultiWidget):
    """Kindly provide the choices dynamically"""
    def __init__(self, attrs=None):
        _widget = (
            Select(attrs=attrs),
            TextInput(attrs=attrs)
        )
        super().__init__(_widget, attrs)

class ModelChoiceInputField(MultiValueField):
    widget = ChoiceInputMultiWidget

    def __init__(self, *args, **kwargs):

        _fields = (
            ModelChoiceField(queryset=Type.objects.all()),
            CharField()
        )
        super().__init__(_fields, *args, **kwargs)

        # Use the auto-generated widget.choices by the ModelChoiceField
        self.widget.widgets[0].choices = self.fields[0].widget.choices
于 2016-10-12T18:29:36.957 に答える
1

のソースを見て__init__くださいforms.MultiValueField:

def __init__(self, fields=(), *args, **kwargs):
    super(MultiValueField, self).__init__(*args, **kwargs)
    # Set 'required' to False on the individual fields, because the
    # required validation will be handled by MultiValueField, not by those
    # individual fields.
    for f in fields:
        f.required = False
    self.fields = fields

したがって、__init__おそらく次のように上書きします。

def __init__(self, *args, **kwargs):
    choices = kwargs.pop("choices",[])
    super(InputAndChoiceField, self).__init__(*args, **kwargs)
    self.fields = (
        fields.CharField(),
        fields.ChoiceField(choices=choices),
    )

パラメータを介してフィールドを取得するのではなく、フィールドを自分で設定しているため、super(MultiValueField, self).__init__(*args, **kwargs)代わりに実行したい場合もあります。super(InputAndChoiceField, self).__init__(*args, **kwargs)

于 2009-10-24T09:28:46.467 に答える
1

ウィジェットで選択肢を渡すと、これが解決しました

class InputAndChoiceWidget(widgets.MultiWidget):
    def __init__(self, attrs=None):
        choices = [('a', 1), ('b', 2)]
        widget = (widgets.TextInput(),
                  widgets.Select(choices=choices)
                 )
        super(InputAndChoiceWidget, self).__init__(widget, attrs=attrs)
于 2010-07-19T10:15:03.757 に答える
0
class HTML5DateInput(DateInput):

    input_type = 'date'


class CustomSelectRangeWidget(forms.MultiWidget):

    def __init__(self, attrs=None, choices = ()):
        widgets = (Select(attrs=attrs, choices=choices), HTML5DateInput(attrs=attrs), HTML5DateInput(attrs=attrs))
        super(CustomSelectRangeWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return [value.field, value.start, value.stop]
        return [None, None, None]

    def format_output(self, rendered_widgets):
        return '-'.join(rendered_widgets)

class CustomSelectRangeField(forms.MultiValueField):

    widget = CustomSelectRangeWidget

    def __init__(self, *args, **kwargs):
        if kwargs.has_key('choices') :
            choices = kwargs.pop('choices')
        else:
            choices = ()
        fields = (
            forms.ChoiceField(choices=choices),  #field with choices,
                                             # so that clean can be passed
            forms.DateField(),
            forms.DateField(),
            )
        super(CustomSelectRangeField, self).__init__(fields=fields, *args, **kwargs)
        #initialize widget with choices.
        self.widget = CustomSelectRangeWidget(choices=choices)

    def compress(self, data_list):
        if data_list:
           #check if datalist has 3 not null values
           if len([v for v in data_list if v not in [None, '']]) == 3:
               out_dict = {'field':data_list[0], 'start':data_list[1], 'stop':data_list[2]}
               return out_dict
       return None
于 2013-05-21T07:09:25.037 に答える