bgarcial bgarcial - 2 months ago 10
Python Question

Making queries ManyToMany relationships

I have a model named

AffectedSegment
which is used for store a corporal segments selection.

class AffectedSegment(models.Model):

SEGMENTO_ESCAPULA = 'Escápula'
SEGMENTO_HOMBRO = 'Hombro'
SEGMENTO_CODO = 'Codo'
SEGMENTO_ANTEBRAZO = 'Antebrazo'
SEGMENTO_CARPO_MUNECA = 'Carpo/Muñeca'
SEGMENTO_MANO = 'Mano'
SEGMENT_CHOICES = (
(SEGMENTO_ESCAPULA, u'Escápula'),
(SEGMENTO_HOMBRO, u'Hombro'),
(SEGMENTO_CODO, u'Codo'),
(SEGMENTO_ANTEBRAZO, u'Antebrazo'),
(SEGMENTO_CARPO_MUNECA, u'Carpo/Muñeca'),
(SEGMENTO_MANO, u'Mano'),
)

affected_segment = models.CharField(
max_length=12,
choices=SEGMENT_CHOICES,
verbose_name='Affected Segment'
)

def __str__(self):
return "%s" % self.affected_segment


I have another model named
Movement
, which is used for store a movement asociated or related with the previous corporal segment entered.

The idea is that one segment (
AffectedSegment
object) can have many movements, and one movement (
Movement
object) can be associated with one or many segments.

class Movement(models.Model):
type = models.CharField(
max_length=255,
verbose_name='Movement type'
)

corporal_segment_associated = models.ManyToManyField(
AffectedSegment,
blank=True,
verbose_name='Affected segment associated')

def __str__(self):
return "%s" % self.type


This two models, I am referencing in this model

class RehabilitationSession(models.Model):

affected_segment = models.ManyToManyField(
AffectedSegment,
verbose_name='Segmento afectado',
#related_name='affectedsegment'
)

movement = models.ManyToManyField(
Movement, # Chained Model
verbose_name='Movement',
#related_name = 'movement'
)


My main doubt is How to can I lookup the content of
affected_segment
and
movement
fields from
RehabilitationSession
model in my html templates.

I am trying pass these data of this way:

My views.py file

class RehabilitationSessionList(ListView):

queryset = RehabilitationSession.objects.all()
context_object_name = 'rehabilitationsessions'
template_name = 'finals_list.html'


And my finals_list.html template is:

<thead>
<tr>
<th>Affected Segment</th>
</tr>
</thead>
<tbody>
{% for a in rehabilitationsessions %}
<tr>
<td>{{ a.affected_segment }}</td>
</tr>
</tbody>
{% endfor %}


But when I access to my template via url, I get this:

enter image description here

Of course, the
RehabilitationSession
model does not have the
affected_segment
and
movement
fields explicitly declared, due to that the ManyToMany relationships create another intermediate models/tables of this way:

enter image description here

Via Django Shell, I can make the queries, navigating through of some of this tables/models

In [21]: RehabilitationSession.objects.filter(movement__type='Extensión')
Out[21]: <QuerySet [<RehabilitationSession: Andrea Vermaelen>]>

In [24]: RehabilitationSession.objects.filter(affected_segment__affected_segment='Codo
...: ')
Out[24]: <QuerySet [<RehabilitationSession: Andrea Vermaelen>]>


My question is how to can I make the queries in my views for the data appear in the templates,

Is possible that my models are not defined correctly? ...

I know that this should not be complex, but I would like receive some orientation about it for I retrieve the segments and movements of a person in a rehabilitation session.

Any orientation is welcome

UPDATE

In relation to the support that @Daniel-Roseman gave me, I extract also the movement field for attach it in the table.

{% for a in rehabilitationsessions %}
{% for r in a.affected_segment.all %}
{% for l in a.movement.all %}
<tr>
<td>{{ a.id }}</td>
<td>{{ a.patient.full_name }}</td>
<td>{{ a.patient.user.birth_date }}</td>
<td>{{ a.patient.user.age }}</td>
<td>{{ a.patient.user.sex }}</td>
<td>{{ a.upper_extremity }} <br/><br/>
<strong>{{ a.pain_extremity }}</strong> </td>
<td>{{ a.patient.dominant_superior_member }}</td>
<td>{{ r.get_affected_segment_display }}</td>

<td>{{ l }}</td>
<td> <button type="button" class="btn btn-xs btn-info"><a href="{% url 'rehabilitationsessions:detail' a.id %}">Ver</a></button></td>
<td><a href="{% url 'rehabilitationsessions:edit' a.id %}">Editar</a></td>

</tr>
{% endfor %}
{% endfor %}
{% endfor %}


And the movement it's showed. Works.
But when I edit the register for add some additional
movement
or additional
affected_segment
, the behavior is that is showed one new record of the this additional segment or movement, although it's not a new record in the database, is a new line of the same record ...

I think that this happened due to my three for loops ...
It's something like this https://cldup.com/JRKuSRFPuD.png

Answer

As you've said, affected_segment is a many-to-many field. That means it refers to many segments (and the name seems wrong, it should be plural). So you can't just output it, you need to iterate through it:

{% for a in rehabilitationsessions %}
   {% for r in a.affected_segment.all %}
       {{ r.get_affected_segment_display }}
   {% endfor %}
{% endfor %}

See that since the field you're interested in on AffectedSegment, itself called affected_segment, has choices assigned, you can use get_affected_segment_display to display the readable value of the choice.

Comments