I have three models: Zone, Stage and ZoneStage with ManyToMany relationship.
the whole point behind is that I have multiple Zone and each Zone has multiple Stages. For each Zone for each Stage I want to display certain VALUE and this is why I create ZoneStage model.
I do not know how to display values as per pictures below. I thought I could do it via:
e.g. for objectz in zone: for objects in stage: for objectzs in zone_stage:
and here some conditions
or
e.g. to try with filters ?
Although, I need some guidance and direction what to read about, how to do it etc and I would appreciate any help with any feedback that can make my life easier to solve this problem.
This is what I get:
My Models:
class Zone(models.Model):
ZONE_N = (
('Z2','Z2'),
('Z4','Z4'),
('Z6.1','Z6.1'),
('Z9LH','Z9LH'),
)
zone_name = models.CharField(max_length=5, choices=ZONE_N, primary_key=True)
zone_number = models.CharField(max_length=5,blank=True)
class Meta:
ordering = ('zone_name',)
def __unicode__(self):
return self.zone_name
class Stage(models.Model):
STAGE_N = (
('S1','S1'),
('S2','S2'),
('S3','S3'),
('S4','S4'),
)
stage_number = models.CharField(max_length=3, choices=STAGE_N, primary_key=True)
stage_name = models.CharField(max_length=50)
zones = models.ManyToManyField('Zone', through='ZoneStage', related_name='status')
class Meta:
ordering = ('stage_number',)
def __unicode__(self):
return self.stage_number
class ZoneStage(models.Model):
zone = models.ForeignKey(Zone)
stage = models.ForeignKey(Stage)
value = models.CharField(max_length=10)
class Meta:
ordering = ('zone',)
def __unicode__(self):
return '%s %s' % (self.zone, self.stage)
My Views:
def index(request):
zs = ZoneStage.objects.all()
z = Zone.objects.all()
s = Stage.objects.all()
context = {'zone_stage': zs, 'zone': z, 'stage': s}
return render(request, 'index.html', context)
My Template:
<table border="1">
<tr>
<td></td>
<td></td>
{% for object in zone %}
<td>{{ object.zone_name }}</td>
{% endfor %}
</tr>
{% for stages in stage %}
<tr>
<td>{{ stages.stage_number }}</td>
<td>{{ stages.stage_name }}</td>
{% for values in stages.zonestage_set.all|dictsort:"zone.zone_name" %}
<td>{{ values.value}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Since your ZoneStage
is an intermediate
model, the zoneid
and stageid
should be ForeignKey
, not ManyToMany
. See example here:
https://docs.djangoproject.com/en/1.8/topics/db/models/#intermediary-manytomany
If you look at your structure, you'll see that it makes sense. Since your ZoneStage
are intersection points, they can't be many to many. Each ZoneStage
will have one unique Zone
and one unique Stage
.
Once this is done, you could access the values this way for example:
<table border="1">
<tr>
<td></td>
<td>{{ object.zone }}</td>
{% for object in zone|dicsort:"zone_name" %}
<td>{{ object.zone_name }}</td>
{% endfor %}
</tr>
{% for objectS in stage %}
<tr>
<td>{{ objectS.stage_no }}</td>
<td>{{ objectS.stage_name }}</td>
{% for zonestages in objectS.zonestage_set.all|dictsort:"zoneid.zone_name" %}
<td>{{ zonestages.zonestage}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
EDIT:
Previous solution works if every intersection has a value. If not one other way to do it would be like this:
<table border="1">
<tr>
<td></td>
<td>{{ object.zone }}</td>
{% for object in zone|dicsort:"zone_name" %}
<td>{{ object.zone_name }}</td>
{% endfor %}
</tr>
{% for objectS in stage %}
<tr>
<td>{{ objectS.stage_no }}</td>
<td>{{ objectS.stage_name }}</td>
{% for zones in zone|dicsort:"zone_name" %}
<td>
{% for zonestages in objectS.zonestage_set.all %}
{% if zonestages.zone == zones %} {{ zonestages.zonestage}}{% endif %}
{% endfor %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>