私はこれを成し遂げるために本当に髪を引っ張ってきました。次のように、モデルの 1 つに 2 つの整数フィールドがあります。
#models.py
class TestModel(models.Model):
"""
This is a test model.
"""
max = models.IntegerField()
min = models.IntegerField()
上記の 2 つの値は相互に関連しているため、カスタム ウィジェットを使用する必要がありました。ここがポイントです。これらのフィールドで 1 つのカスタム ウィジェット (MultiWidget) を使用する必要がありますが、値をデータベース内の別の列に保持したい [実際には解析したくなく、さらに検索機能は上記のフィールドは別々に保存したいので、別々に保存したい]。
カスタム ウィジェットは単一のモデル フィールドからの値のみを受け入れるため、上記のモデルの ModelForm で使用するカスタム フォーム フィールドを作成することにしました。
これが私のフォームの外観です。
class MinMaxField(forms.MultiValueField):
def __init__(self, *args, **kwargs):
all_fields = (
forms.CharField(),
forms.CharField(),
)
super(MinMaxField, self).__init__(all_fields, *args, **kwargs)
def compress(self, values):
if values:
return '|'.join(values)
return ''
class TestModelForm(forms.ModelForm):
minmax = MinMaxField(widget=widgets.MinMaxWidget(),
required=False)
class Meta:
model = models.TestModel
fields = ('min', 'max', 'minmax')
widgets = {
'min' : forms.HiddenInput(),
'max' : forms.HiddenInput(),
}
def full_clean(self, *args, **kwargs):
if 'minmax_0' in self.data:
newdata = self.data.copy()
newdata['min'] = self.data['minmax_0']
newdata['max'] = self.data['minmax_1']
self.data = newdata
super(TestModelForm, self).full_clean(*args, **kwargs)
上記のフォームは、基本的にモデル フィールドを非表示にし、minmax
次のようにカスタム ウィジェットを使用するフィールドのみを表示します。
class MinMaxWidget(widgets.MultiWidget):
def __init__(self, attrs=None):
mwidgets = (widgets.Select(attrs=attrs, choices=MIN),
widgets.Select(attrs=attrs, choices=MAX))
super(MinMaxWidget, self).__init__(mwidgets, attrs)
def value_from_datadict(self, data, files, name):
try:
values = [widget.value_from_datadict(data, files, name + '_%s' % i)\
for i, widget in enumerate(self.widgets)]
value = [int(values[0]), int(values[1])]
except ValueError:
raise ValueError('Value %s for %s did not validate. \
a list or a tuple expected' % (value, self.widget))
return value
def decompress(self, value):
if value:
if isinstance(value, list):
return value
return [value[0], value[1]]
return [None, None]
def format_output(self, rendered_widgets):
rendered_widgets.insert(0, '<span class="multi_selects">')
rendered_widgets.insert(-1, '<label id="min">Min</label>')
rendered_widgets.append('<label id="max">Max</label></span>')
return u''.join(rendered_widgets)
この時点で、すべてが正常に機能し、値はそれぞれのフィールドに個別に保存されます。しかし、オブジェクトのインスタンスでフォームを編集しようとすると問題が発生しTestModel
ます。編集の場合、フォームがレンダリングされると、実際の値は隠しフィールドmin
とmax
入力フィールドに格納され、最小最大フィールドには値がありません。[もちろんフォームフィールドです。]
私がしなければならないオプションは何ですか
およびフィールド
minmax
からフォーム フィールドの値を事前入力します。[注: Javascript や jQuery を使用しない場合]min
max
または、2 つの異なるモデル フィールドの値を使用する MultiWidget を作成します。
どんな助けでも大歓迎です。ありがとう。