Showing value of many2many relationship

Hej!
I have a Many2Many relationship that I want to show in a result table, but all I get is somethings.Model.None. Alle my other relationships and fields are shown perfectly. Does anyone have an idea?

I use {% for i in somethings %}
and then {{ i.related_name}}

In my Model (with the related_name) I do have a str funktion and in the admin area everything looks fine and I get the value.

Thanks for any recommendations and help!

We’ll need to see the models, view, and template involved here to do any real diagnosis.
When posting code here, enclose it between lines of three backtick - ` characters. You’ll have a line of ```, then your code (or template), then another line of ```. This forces the forum software to keep the formatting of your code, which is critical with Python.

Hej Ken!

I’m sorry. Thought this might be a simple solution where I just can’t get my head around.

# plants/models.py

class Plant(models.Model):
    name = models.CharField(
        max_length=200
    )
    plant_type = models.ForeignKey(
        PlantType,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        related_name="plant_type",
    )
    used_xducts = models.ManyToManyField(
        Xduct,
        through="UsedXduct",
        blank=True,
        related_name="used_in_plant"
    )


class OperatingHour(models.Model):
    plant = models.ForeignKey(
        Plant,
        on_delete=models.PROTECT,
        related_name="operatinghour"
    )
    value = models.FloatField()


class UsedXduct(models.Model):
    plant = models.ForeignKey(
        Plant,
        on_delete=models.PROTECT,
        related_name="used_in_plant"
    )
    xduct = models.ForeignKey(
        Xduct,
        on_delete=models.PROTECT,
        related_name="xduct"
    )


class PlantType(models.Model):
    name_english = models.CharField(
        max_length=200
    )
# xducts/models.py

class Xduct(models.Model):
    code = models.CharField(
        max_length=20,
        unique=True,
    )    
    name_english = models.CharField(
        max_length=200,
        unique=True
    )
# views.py

def plants_view(request):
    plants = Plant.objects.all()

    myFilter = PlantFilter(request.GET, queryset=plants)
    plants = myFilter.qs

    context = {"plants": plants, "myFilter": myFilter}

    return render(request, 'plants/search_table.html', context)
<!-- search_table.html -->

{% block content %}
<br>
	<div class="row collapse {% if show_form %} show  {% endif %}" id="form-holder">
		<div class="row">
			<div class="col">
				<div class="card card-body">

					<form method="get">
						{{myFilter.form.as_p}}

						<button class="btn-primary" type="submit">Search</button>
					</form>

				</div>
			</div>
		</div>
	</div>
</br>

		<div class="row">
			<div class="col-md">
				<div class="card card-body">
					<h5>Plants</h5>
				</div>
				<div class="card card-body">
					<table class="table table-sm">
						<tr>
							<th>Name</th>
							<th>Plant type</th>
							<th>Used Xducts</th>
							<th>Operating Hours</th>

						</tr>

						{% for plant in plants %}
						<tr>
							<td>{{plant.name}}</td>
							<td>{{plant.plant_type}}</td>
							<td>{{plant.used_in_plant}}</td>
							<td>{{plant.operatinghour}}</td>

						</tr>

						{% endfor %}

					</table>
				</div>
			</div>

		</div>

{% endblock content %}

# filters.py

class PlantFilter(django_filters.FilterSet):
    name = CharFilter(field_name="name", lookup_expr='icontains')

    class Meta:
        model = Plant
        fields = '__all__'

plant_type and name are working fine, the used_xducts and operatinghour not.
Also the filter does work. There I can see the value and I can choose it and filter for the xduct. The result is correct.

I tried several versions in the template, like,
{{plants.used_in_plant.xduct}}
or {{plants.used_xducts.code}} but then the field is empty and I don’t even get the plants.UsedXducts.None output.

And I checked multiple times if I have data for the plant. There should be something, as the filter can filter for that info!

Getting rather frustrated :smiley:

Do you have any idea? I’m very thankful for every idea!

This is covered in the Related Objects Reference docs

Inside your template, if you’re rendering a list of Plant, and within each plant you want to render the list of Xduct, it would be something very similar to:

{% for each_plant in plant %}
    {% for each_xduct in each_plant.used_xducts.all %}
        render individual fields as each_xduct.whatever
...

on the reverse side of this relationship, you would reference the set of related Plant from an Xduct through either the related_name (used_in_plant) if one is defined or by using the _set suffix on the model name (e.g. plant_set)

(Note: I asked for the source because I’ve found that in most cases my answer is easier to understand if I present it in terms of the actual models being worked with.)

1 Like

Hej Ken!
Thanks for your response!
I already read the docs, but there is no example of how to get it working in the template. I do understand how they are connected and all, but it won’t show the values.

when I try

<!-- search_table.html -->

   					<tr>
   						<td>Xduct</td>
   					</tr>

   					{% for plant in plants %}
   						{% for xduct in plant.used_xducts.all %}

   					<tr>
   						<td>{{xduct.xduct}}</td>
   					</tr>

   						{% endfor %}
   					{% endfor %}

(hope I got what you meant in your reply) I still get the plants.UsedXduct.None or xducts.Xduct.None (depending on {{xduct.xduct}} or plant.used_xducts .
If I put something third (the name of the variable of the desired value) I get an empty field.

Do I need to change my model to make it work?

Thanks for your time!

The first xduct is the reference to the xduct object. You need to render the individual fields. e.g. {{ xduct.code }}

1 Like

That was dumb of me :smiley:
Thank you very much!!
This was so helpful!

Can I put an if around? The field for the xducts is not mandatory and can be empty, therefor would not be shown in the table.
And I have multiple models that I need to integrate like that. Can I just put it all in one or do I need to nest it all together?

Why don’t you try it and see! (Keep in mind that an empty loop doesn’t render anything within the loop - so if there’s no data, there’s no need to guard it with an if.)

Unfortunately, I’m not sure I understand what you’re trying to address here, but I’m going to give a qualified ‘Yes, you can “integrate” multiple models like that’ under the assumption that what you mean by “integrate multiple models” in this context is what I think you mean by it.

If I do it like the following I get the error: Could not parse the remainder: ’ plant.operatinghour’ from ‘if plant.operatinghour’


{% for plant in plants %}
						<tr>
							<td>{{plant.name}}</td>
							{% for xduct in plant.used_xducts.all %}
								<td>{{xduct.code}}</td>
							{% endfor %}

							{{if hour in plant.operatinghour = True}}
								{% for hour in plant.operatinghour.all %}
								<td>{{hour.value}}</td>
								{% endfor %}
							{{endif}}

if I leave it like that it will only write something in the cell if there is an info for that variable, otherwise it will just go to the next {{for ...}} resolving in a table that has no solid columns and width. Then I will get operating hour under the xduct, if the next plant doesn’t have an xduct.

First, review the syntax of the if tag

Second, I don’t understand what you’re trying to accomplish by:

The reference plant.operatinghour is not a single object. It’s a reference to a related manager (link provided above).

If you’re looking to check the value of hour.value for each instance of plant.operatinghour, then the if tag needs to be inside the loop where you would have an instance of plant.operatinghour to access.

If you’re just looking to see if there are any objects in that reference to plant.operatinghour, you don’t need to do that. If there aren’t any objects in the relationship list, the loop isn’t going to execute.

Hej Ken,

I have models for the xducts, the operatinghours, the employees, the owner, and so on. All similiar to each other constructionwise. None of the mentioned is mandatory.
I want a table with a column for each of the information, filled in with the value of a variable, if there is an information/input given. If not the cell should be empty.
To get all the values I need the for loop for each. Otherwise I’ll always get the something.Model.None output.
I therefore need something to check if there is an information befor I can loop through for.

Thanks for all the answers!
I hope I made my problem a little clearer now.

Yes, you need the for loop for each.

However, if there is no data, the for loop does not render any data. You won’t get a something.Model.None. You won’t get anything.

Yes, I know. That is my problem. I then want an empty cell but now the value of the next column is written in that cell.

I attached a screenshot on how it looks right now.

This is not the optimum. I want clear columns with empty cells (like with the operating environment). All mushed together is not readable.

See the for.. empty variant of the for tag. (It’s really worth the time to browse all of the available tags just to get an idea of the different options available.)

1 Like