O
O
olexndr0902021-05-05 17:48:59
Django
olexndr090, 2021-05-05 17:48:59

How to output related table fields by ManyToMany Through in html template?

Here are the models:

class Products(models.Model):
    code = models.IntegerField(blank=True, null=True, help_text="Код товару для швидкого пошуку")
    product_name = models.CharField(max_length=200, help_text="Назва запчастини")
    group = models.ForeignKey(Groups,on_delete=models.CASCADE, blank=True, null=True, help_text="Група до якої  відноситься запчастина")

    def __str__(self):
        return self.product_name


class Connections(models.Model):
    service = models.ForeignKey(Services, on_delete=models.CASCADE, blank=True, null=True, help_text="Послуга до якої додати запчастини")
    product_item = models.ManyToManyField('Products', through='ThroughProducts')

    def __str__(self):
        return self.service.service_name

class ThroughProducts(models.Model):
    connection = models.ForeignKey(Connections, on_delete=models.CASCADE, related_name='connections')
    product = models.ForeignKey('Products', on_delete=models.CASCADE, related_name='product')
    value_product = models.IntegerField()

    def __str__(self):
        return self.connection.service.service_name

They work. In the admin panel, I added several values ​​​​and everything is displayed, but I cannot access the attached fields in the template.
I'm trying the following:
<ul>
{% for connection in connections %}
   <li class="connect-service">{{ connection.service.code }}</li>
    <ul>
        {% for n_product in connection.throughproducts_set.all %}
       <li class="connect-product select-item-product" data-index="{{ n_product.id }}">{{ n_product.value_product }}<input type="checkbox" class="option-add" value="1"></li>
        {% endfor %}
    </ul>
{% endfor %}
</ul>

Outputs nothing. In any combination, even if there is a related_name.
The following option works:
<ul>
{% for connection in connections %}
   <li class="connect-service">{{ connection.service.code }}</li>
    <ul>
        {% for n_product in connection.product_item.all %}
            {% for item in value %}
                {% if item.product == n_product and item.connection == connection %}
                    <li class="connect-product select-item-product" data-index="{{ n_product.id }}">{{ n_product.product_name }} - {{ item.value_product }}<input type="checkbox" class="option-add" value="1"></li>
                {% endif %}
            {% endfor %}
        {% endfor %}
    </ul>
{% endfor %}
</ul>

But it has too many cycles. With a lot of data, this is inefficient.
How can I get the same result as in the working version, but with the correct code?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
O
olexndr090, 2021-05-20
@olexndr090

I found the following solution, I created a function in the model for filtering and it can be called in the template.

class Products(models.Model):
    code = models.IntegerField(blank=True, null=True, help_text="Код товару для швидкого пошуку")
    product_name = models.CharField(max_length=200, help_text="Назва запчастини")
    group = models.ForeignKey(Groups,on_delete=models.CASCADE, blank=True, null=True, help_text="Група до якої  відноситься запчастина")

    def __str__(self):
        return self.product_name

    def get_products(self):
        return ThroughProducts.objects.filter(product=self.id)

The template calls it like this:
{% for n_product in product.get_products %}
       <li>{{ n_product.value_product }}</li>
        {% endfor %}

R
RipperZX, 2021-05-06
@RipperZX

I think it's worth thinking about putting the logic in view., you shouldn't do this with a template engine!

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question