Almacenando ManyToMany fields en un formulario forms.ModelForm

Pregunta de la clase:
Bernardo Augusto García Loaiza

Bernardo Augusto García Loaiza

Pregunta
studenthace 9 años

Estoy construyendo un formulario basado en algunos modelos en uno de los cuales tengo atributos con relaciones ManyToMany a otros. La situación es la siguiente:

Modelo

CorporalSegment

class CorporalSegment(models.Model):    SEGMENTO_HOMBRO = 'Hombro'    SEGMENTO_CODO = 'Codo'    SEGMENTO_ANTEBRAZO = 'Antebrazo'    SEGMENTO_MANO = 'Mano'    SEGMENT_CHOICES = (        (SEGMENTO_HOMBRO, u'Hombro'),        (SEGMENTO_CODO, u'Codo'),        (SEGMENTO_ANTEBRAZO, u'Antebrazo'),        (SEGMENTO_MANO, u'Mano'),    )    corporal_segment = models.CharField(        max_length=12,        choices=SEGMENT_CHOICES,        blank=False,    )    class Meta:        verbose_name_plural = 'Segmentos Corporales'    def __str__(self):        return "%s" % self.corporal_segment

Modelo Movement

class Movements(models.Model):    name = models.CharField(        max_length=255,        verbose_name='Movimiento'    )    class Meta:        verbose_name_plural = 'Movimientos'    def __str__(self):        return "%s" % self.name

Modelo Metric

class Metrics(models.Model):    name = models.CharField(        max_length=255,        blank=True,        verbose_name='Nombre'    )    value = models.DecimalField(        max_digits = 5,        decimal_places = 3,        verbose_name = 'Valor',        null = True,        blank = True    )    class Meta:        verbose_name = 'Métrica'    def __str__(self):        return "{},{}".format(self.name, self.value)

Mi propósito es poder almacenar en un formulario múltiples valores/instancias de los modelos

CorporalSegment
,
Movement
y
Metric
, por lo cual he creado el modelo
PatientMonitoring
de esta manera:

class PatientMonitoring(models.Model):    patient = models.ForeignKey(...)    medical = models.ForeignKey(...)    # Mis campos que son many to many a los modelos en cuestión mencionados    corporal_segment = models.ManyToManyField(CorporalSegment, verbose_name='Segmentos Corporales')    movement = models.ManyToManyField(Movements, verbose_name='Movimientos')    metrics = models.ManyToManyField(Metrics, verbose_name='Métricas', )    class Meta:        verbose_name = 'Monitoreo del paciente'    def __str__(self):        return "%s" % self.patient

Este es mi archivo views.py en relación a las operaciones de escritura con el modelo

PatientMonitoring

class PatientMonitoringCreate(CreateView):    model = PatientMonitoring    form_class = PatientMonitoringForm    success_url = reverse_lazy('patientmonitoring:list') class PatientMonitoringUpdate(UpdateView):    model = PatientMonitoring    form_class = PatientMonitoringForm    success_url = reverse_lazy('patientmonitoring:list')

Este es mi archivo forms.py el cual en su método

save(...)
es donde creo que debo hacer más énfasis ...

from django import forms from .models import PatientMonitoring from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit class PatientMonitoringForm(forms.ModelForm):    def __init__(self, *args, **kwargs):        super(PatientMonitoringForm, self).__init__(*args, **kwargs)        self.helper = FormHelper()        self.helper.add_input(Submit('submit', u'Save'))    # I think so that here is my problem ...    def save(self, commit=True):        patient_monitoring = super(PatientMonitoringForm, self).save(commit=False)        patient = self.cleaned_data['patient']        if commit:            patient_monitoring.save()        return patient_monitoring    class Meta:        model = PatientMonitoring        fields = ['patient', 'medical','corporal_segment','movement','metrics']

Y mi template

patientmonitoring_form.html
es:

{% extends 'base.html' %} {% load crispy_forms_tags %} {% block title %}Crear Registro de Monitoreo de Paciente{% endblock %} {% block content %} <div>    {% crispy form %}    {% csrf_token %} </div> {% endblock %}

Estoy construyendo un formulario basado en algunos modelos en uno de los cuales tengo atributos con relaciones ManyToMany a otros. La situación es la siguiente:

Modelo

CorporalSegment

class CorporalSegment(models.Model):    SEGMENTO_HOMBRO = 'Hombro'    SEGMENTO_CODO = 'Codo'    SEGMENTO_ANTEBRAZO = 'Antebrazo'    SEGMENTO_MANO = 'Mano'    SEGMENT_CHOICES = (        (SEGMENTO_HOMBRO, u'Hombro'),        (SEGMENTO_CODO, u'Codo'),        (SEGMENTO_ANTEBRAZO, u'Antebrazo'),        (SEGMENTO_MANO, u'Mano'),    )    corporal_segment = models.CharField(        max_length=12,        choices=SEGMENT_CHOICES,        blank=False,    )    class Meta:        verbose_name_plural = 'Segmentos Corporales'    def __str__(self):        return "%s" % self.corporal_segment

Modelo

Movement

class Movements(models.Model):    name = models.CharField(        max_length=255,        verbose_name='Movimiento'    )    class Meta:        verbose_name_plural = 'Movimientos'    def __str__(self):        return "%s" % self.name

Modelo

Metric

class Metrics(models.Model):    name = models.CharField(        max_length=255,        blank=True,        verbose_name='Nombre'    )    value = models.DecimalField(        max_digits = 5,        decimal_places = 3,        verbose_name = 'Valor',        null = True,        blank = True    )    class Meta:        verbose_name = 'Métrica'    def __str__(self):        return "{},{}".format(self.name, self.value)

Mi propósito es poder almacenar en un formulario múltiples valores/instancias de los modelos

CorporalSegment
,
Movement
y
Metric
, por lo cual he creado el modelo
PatientMonitoring
de esta manera:

class PatientMonitoring(models.Model):    patient = models.ForeignKey(...)    medical = models.ForeignKey(...)    # Mis campos que son many to many a los modelos en cuestión mencionados    corporal_segment = models.ManyToManyField(CorporalSegment, verbose_name='Segmentos Corporales')    movement = models.ManyToManyField(Movements, verbose_name='Movimientos')    metrics = models.ManyToManyField(Metrics, verbose_name='Métricas', )    class Meta:        verbose_name = 'Monitoreo del paciente'    def __str__(self):        return "%s" % self.patient

Este es mi archivo views.py en relación a las operaciones de escritura con el modelo

PatientMonitoring

class PatientMonitoringCreate(CreateView):    model = PatientMonitoring    form_class = PatientMonitoringForm    success_url = reverse_lazy('patientmonitoring:list') class PatientMonitoringUpdate(UpdateView):    model = PatientMonitoring    form_class = PatientMonitoringForm    success_url = reverse_lazy('patientmonitoring:list')

Este es mi archivo forms.py el cual en su método

save(...)
es donde creo que debo hacer más énfasis ...

from django import forms from .models import PatientMonitoring from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit class PatientMonitoringForm(forms.ModelForm):    def __init__(self, *args, **kwargs):        super(PatientMonitoringForm, self).__init__(*args, **kwargs)        self.helper = FormHelper()        self.helper.add_input(Submit('submit', u'Save'))    # I think so that here is my problem ...    def save(self, commit=True):        patient_monitoring = super(PatientMonitoringForm, self).save(commit=False)        patient = self.cleaned_data['patient']        if commit:            patient_monitoring.save()        return patient_monitoring    class Meta:        model = PatientMonitoring        fields = ['patient', 'medical','corporal_segment','movement','metrics']

Y mi template

patientmonitoring_form.html
es:

{% extends 'base.html' %} {% load crispy_forms_tags %} {% block title %}Crear Registro de Monitoreo de Paciente{% endblock %} {% block content %} <div>    {% crispy form %}    {% csrf_token %} </div> {% endblock %}

Lo que me sucede es que cuando deseo grabar un registro o instancia de

PatientMonitoring
en su respectivo formulario, los atributos
corporal_segment
(Segmentos Corporales)
movement
(Movimientos) y
metrics
(Metricas) en el formulario, no son almacenados (recuadros rojos), pero los demás si se almacenan.

Este comportamiento es algo extraño para mi, dado que a través del formulario de Django admin, el modelo PatientMonitoring si se almacena con la totalidad de sus campos, incluyendo los many to many mencionados.

¿Qué puedo estar ignorando al momento de almacenar valores en mi formulario

PatientMonitoringForm
en
forms.py
?

pd: Me disculpo de antemano con ustedes porque la pregunta me salió algo extensa, pero no sabía como dar los detalles del contexto de forma mas resumida.

Muchas gracias

1 respuestas
para escribir tu comentario

    Team Platzihace 9 años

    No entiendo, para que sobre escribes el método save, si lo único que haces es guardar el paciente en una variable la cual no usas para nada.

    Puedes explicar para que haces eso, prueba a no sobre escribir el save y guardar, puede ser esa la función que te da problema.

Curso de Python y Django 2016

Curso de Python y Django 2016

Aprende Python desde cero y crea tu primera aplicación web completa en Django. Entiende las bases del lenguaje, sus funciones, conoce cómo conectarte a bases de datos y termina creando una API REST de manera profesional para tu app.

Curso de Python y Django 2016
Curso de Python y Django 2016

Curso de Python y Django 2016

Aprende Python desde cero y crea tu primera aplicación web completa en Django. Entiende las bases del lenguaje, sus funciones, conoce cómo conectarte a bases de datos y termina creando una API REST de manera profesional para tu app.