J'ai vraiment tiré mes cheveux pour faire cela. J'ai 2 champs entiers dans un de mes modèles comme suit:est-il possible pour un multi-widget d'utiliser deux champs de modèle différents
#models.py
class TestModel(models.Model):
"""
This is a test model.
"""
max = models.IntegerField()
min = models.IntegerField()
Comme les deux valeurs ci-dessus sont je les voulais liés entre eux d'utiliser un widget personnalisé. Maintenant, voici le point, je veux que ces champs utilisent un seul widget personnalisé (MultiWidget) mais je veux aussi garder les valeurs dans des colonnes séparées dans la base de données [Ne pas vraiment vouloir analyser les choses et de plus la fonctionnalité de recherche utilisera le ci-dessus les champs séparément, donc je veux juste les stocker séparément]. Un widget personnalisé n'accepterait que la valeur d'un seul champ de modèle, j'ai donc décidé de créer un champ de formulaire personnalisé à utiliser dans le ModelForm pour le modèle ci-dessus.
Voici à quoi ressemble mon formulaire.
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)
Le formulaire ci-dessus se cache essentiellement les champs du modèle et ne montre que le champ minmax
qui utilise un widget personnalisé comme suit:
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)
maintenant à ce tout moment fonctionne très bien, les valeurs sont sauvés séparément dans leurs champs respectifs. Mais le problème se pose lorsque j'essaie d'éditer le formulaire avec une instance d'un objet TestModel
. Dans le cas de l'édition, lorsque le formulaire est rendu, les valeurs réelles sont stockées dans les champs de saisie cachés min
et max
et le champ minmax n'a pas de valeur. [Ofcourse comme il est un champ de formulaire.]
Quelles sont les options que je dois
Soit préremplir la valeur du champ de formulaire
minmax
desmin
etmax
champs. [Remarque: sans utiliser JavaScript ou jQuery]Ou de créer un MultiWidget qui utilise les valeurs de deux champs de modèle différents.
Toute aide serait appréciée. Merci.
quelle version utilisez-vous? –
Quelqu'un at-il trouvé un moyen de le faire ... même problème ici ... – gabn88