Storing ManyToMany fields in a forms.ModelForm form

2

I am building a form based on some models in one of which I have attributes with ManyToMany relationships to others. The situation is as follows:

Model 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

Model 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

Model 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)

My purpose is to be able to store in a form multiple values / instances of the models CorporalSegment , Movement and Metric , for which I created the model PatientMonitoring in this way:

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

This is my views.py file in relation to the write operations with the model 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')

This is my forms.py file which in its method save(...) is where I think I should do more emphasis ...

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']

And my template patientmonitoring_form.html is:

{% 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 %}

What happens to me is that when I want to record a record or instance of PatientMonitoring in its respective form, the attributes corporal_segment (Body Segments) movement (Movements) and metrics (Metrics) in the form , they are not stored (red boxes), but the others are stored.

This behavior is somewhat strange for me, given that through the Django admin form, the PatientMonitoring model is stored with all of its fields, including the many to many mentioned.

What can I be ignoring when I store values in my form PatientMonitoringForm in forms.py ?

    
asked by bgarcial 19.07.2016 в 04:47
source

1 answer

1

I was overwriting in forms.py the save() method where I was giving commit = False in this way

def save(self, commit=False):
        patient_monitoring = super(PatientMonitoringForm, self).save(commit=False)
        patient = self.cleaned_data['patient']

        if commit:
            patient_monitoring.save()
        return patient_monitoring

and if I give it commit = False the form is not immediately saved in the POST

According to the documentation link go to commit = True and already save the data I want the form.

But I'm also here keeping the patient in a variable called patient that I do not use at all: In this part

patient = self.cleaned_data['patient'] 

If I do not overwrite the save() method, that is, if I remove it, the form also saves all the fields that correspond to the models of CorporalSegment , and Movement .

In that same link that I refer to in the documentation, we talk about calling the method save_m2m() when you have the commit = False and in my case it was like that and I have two fields in my model PatientMonitoring that have ManyToMany relationships to two others Models (Movement and CorporalSegment)

What it says is that ManyToMany relationships require that the parent object be recorded first and with commit = False is not allowed to do this.

I have to look at this part of save_m2m() that I think is appropriate for what I want.

    
answered by 27.07.2016 / 17:53
source