widgets radioselect form example python django django-forms django-admin

python - radioselect - select django



Anulando el método guardar en Django ModelForm (1)

Tengo problemas para anular un método de guardado de ModelForm . Este es el error que estoy recibiendo:

Exception Type: TypeError Exception Value: save() got an unexpected keyword argument ''commit''

Mis intenciones son hacer que un formulario envíe muchos valores para 3 campos, luego crear un objeto para cada combinación de esos campos y guardar cada uno de esos objetos. Un codazo útil en la dirección correcta sería ace.

Archivo models.py

class CallResultType(models.Model): id = models.AutoField(db_column=''icontact_result_code_type_id'', primary_key=True) callResult = models.ForeignKey(''CallResult'', db_column=''icontact_result_code_id'') campaign = models.ForeignKey(''Campaign'', db_column=''icampaign_id'') callType = models.ForeignKey(''CallType'', db_column=''icall_type_id'') agent = models.BooleanField(db_column=''bagent'', default=True) teamLeader = models.BooleanField(db_column=''bTeamLeader'', default=True) active = models.BooleanField(db_column=''bactive'', default=True)

Archivo forms.py

from django.forms import ModelForm, ModelMultipleChoiceField from callresults.models import * class CallResultTypeForm(ModelForm): callResult = ModelMultipleChoiceField(queryset=CallResult.objects.all()) campaign = ModelMultipleChoiceField(queryset=Campaign.objects.all()) callType = ModelMultipleChoiceField(queryset=CallType.objects.all()) def save(self, force_insert=False, force_update=False): for cr in self.callResult: for c in self.campain: for ct in self.callType: m = CallResultType(self) # this line is probably wrong m.callResult = cr m.campaign = c m.calltype = ct m.save() class Meta: model = CallResultType

Archivo admin.py

class CallResultTypeAdmin(admin.ModelAdmin): form = CallResultTypeForm


En tu save debes tener el argumento commit . Si algo sobrescribe su formulario, o quiere modificar lo que está guardando, lo hará save(commit=False) , modificar el resultado, y luego guardarlo.

Además, su ModelForm debe devolver el modelo que está guardando. Por lo general, el guardado de un ModelForm se verá algo así como:

def save(self, commit=True): m = super(CallResultTypeForm, self).save(commit=False) # do custom stuff if commit: m.save() return m

Lea sobre el método de save .

Finalmente, mucho de este ModelForm no funcionará solo por la forma en que está accediendo a las cosas. En lugar de self.callResult , necesita usar self.fields[''callResult''] .

ACTUALIZACIÓN : En respuesta a su respuesta:

Aparte: ¿por qué no usar ManyToManyField s en el Modelo para que no tenga que hacer esto? Parece que está almacenando datos redundantes y haciendo más trabajo para usted (y para mí :P ).

from django.db.models import AutoField def copy_model_instance(obj): """ Create a copy of a model instance. M2M relationships are currently not handled, i.e. they are not copied. (Fortunately, you don''t have any in this case) See also Django #4027. From http://blog.elsdoerfer.name/2008/09/09/making-a-copy-of-a-model-instance/ """ initial = dict([(f.name, getattr(obj, f.name)) for f in obj._meta.fields if not isinstance(f, AutoField) and not f in obj._meta.parents.values()]) return obj.__class__(**initial) class CallResultTypeForm(ModelForm): callResult = ModelMultipleChoiceField(queryset=CallResult.objects.all()) campaign = ModelMultipleChoiceField(queryset=Campaign.objects.all()) callType = ModelMultipleChoiceField(queryset=CallType.objects.all()) def save(self, commit=True, *args, **kwargs): m = super(CallResultTypeForm, self).save(commit=False, *args, **kwargs) results = [] for cr in self.callResult: for c in self.campain: for ct in self.callType: m_new = copy_model_instance(m) m_new.callResult = cr m_new.campaign = c m_new.calltype = ct if commit: m_new.save() results.append(m_new) return results

Esto permite la herencia de CallResultTypeForm , en caso de que sea necesario.