I do have the following Issue - I want to display all of the bundles with their component relations in a template:
Here is my ORM-Model:
class Component(models.Model):
plenty_var_number = models.CharField(max_length=120, default=None, unique=True, null=True)
plenty_var_id = models.CharField(max_length=120, default=None, unique=True)
description = models.TextField(max_length=1000)
category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, null=False)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
def __str__(self):
return f"{self.category.name} - {self.plenty_var_number}"
class Bundle(models.Model):
active = models.BooleanField(default=True)
plenty_var_number = models.CharField(max_length=120, default=None, unique=True, null=True)
plenty_var_id = models.CharField(max_length=120, null=True, default=None)
car = models.ForeignKey(Car, on_delete=models.DO_NOTHING)
# m2m defined by BundleComponentRelation
components = models.ManyToManyField(Component, through="BundleComponentRelation")
linked_to_plenty = models.BooleanField(default=False)
price = models.DecimalField(max_digits=10, decimal_places=2, default=-1.00)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
class BundleComponentRelation(models.Model):
component = models.ForeignKey(Component, on_delete=models.DO_NOTHING)
bundle = models.ForeignKey(Bundle, on_delete=models.DO_NOTHING)
qty = models.IntegerField(default=1)
updated_at = models.DateTimeField(auto_now=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
I have played around with select_related
and prefetch_related
in my view to pass them via context to the template to display it for my users:
html-template:
{% for bundle in bundles %}
<tr>
<td><p >{{ bundle.plenty_var_number }}</p></td>
<td>{{ bundle.price }}</td>
<td><p >{{ bundle.car }}</p>
<p >{{ bundle.car.roof_type }}</p>
<p >BJ: {{ bundle.car.production_start }}
- {{ bundle.car.production_end }}</p>
</td>
{# Bundle Component Relations here #}
<td style="font-size: 1em;">
<a href={% url "edit_bundle" bundle.pk %}><i
></i></a>
<a href={% url "sync_bundle" bundle.pk %}><i
></i></a>
</td>
</tr>
{% endfor %}
views.py
def bundle_view(request):
bundles = Bundle.objects.prefetch_related('components').all()
print(bundles[0].components)
return render(request, "all_bundles.html", context={"bundles": bundles})
The output of print(bundles[0].components)
is bundle.Component.None
I understood the forward usage of select_related
but I do have trouble understanding the reverse thinking of the prefetch_related
in my situation.
I think my problem is the lookup syntax of prefetch_related
, but I might be wrong here.
What am I missing here?
Thanks in advance.
EDIT
I tried:
{% for bundle in bundles %}
<tr>
<td><p >{{ bundle.plenty_var_number }}</p></td>
<td>{{ bundle.price }}</td>
<td><p >{{ bundle.car }}</p>
<p >{{ bundle.car.roof_type }}</p>
<p >BJ: {{ bundle.car.production_start }}
- {{ bundle.car.production_end }}</p>
</td>
{% for comp_rel in bundle.components.all %}
{{ comp_rel }}
{% endfor %}
<td style="font-size: 1em;">
<a href={% url "edit_bundle" bundle.pk %}><i
></i></a>
<a href={% url "sync_bundle" bundle.pk %}><i
></i></a>
</td>
</tr>
{% endfor %}
I wanted to get only the related components to the currently iterated bundle. The problem I get here is that the template triggers the database again:
Simply using the bundle.component
in the template led to
ManyRelatedManager object is not iterable TypError
CodePudding user response:
There is no problem with your prefetch_related, but the way you want to access these objects, you should do bundles[0].components.all()
because objects fetched with reverse relation can be accessed same way as M2M fields
CodePudding user response:
Are you sure it must be prefetch_related
? I think it must be select_related
.
I think you should use Bundle.objects.select_related('components').all()
and Component.objects.prefetch_related('bundle_set').all()
with your models. But I'm not sure.
And what about template error - you shoud use {% for component in bundle.components.all %}
in template.
And there same problem, mb will helpfull.