Как выполнить итерацию в подпунктах объекта в шаблоне django

views.py:

from django.views import generic
from .models import Servico


class ServicoView(generic.DetailView):
    model = Servico
    context_object_name = 'servico'
    template_name = 'servico.html'

models.py:

from djongo import models


class PublicoAlvo(models.Model):
    def __str__(self):
        return ''
    alvo1 = models.CharField(max_length = 126)
    alvo2 = models.CharField(max_length = 126, blank = True, default = '')
    class Meta:
        abstract = True

class Servico(models.Model):
    t_id = models.CharField(primary_key = True, unique = True, max_length = 252)
    alvos = models.EmbeddedField(
        model_container = PublicoAlvo
    ) 

urls.py:

from django.urls import path
from . import views


urlpatterns = [
    path('servicos/<slug:pk>/', views.ServicoView.as_view(), name = 'servico')
]

I think these are the relevant files in my Django app folder. Back to the question, how can I iterate over the values that are going to be stored in servico.alvos in my template? If I want to show t_id, I just use {{ servico.t_id }} and it works fine. I could write something like:

{{ servico.alvos.alvo1 }}
{{ servico.alvos.alvo2 }}

И это покажет значения, которые я хочу, но это сделает все более уродливым и ограниченным (представьте, если я решу изменить модель и добавить больше 6 значений в класс PublicoAlvo). Я попробовал следующее:

{% for alvo in servico.alvos.all %}
    {{ alvo }}
{% endfor %}

и

{% for alvo in servico.alvos.items %}
    {{ alvo }}
{% endfor %}

Но у меня ничего не печатается. Когда я пытаюсь:

{% for alvo in servico.alvos %}
    {{ alvo }}
{% endfor %}

Я получаю 'PublicoAlvo' object is not iterable

Есть ли способ получить то, что я хочу, используя цикл в моем шаблоне или изменив что-то в моем models.py?

Попробовать

{{ servico.t_id }}
{{ servico.alvos }}

Затем в вашем models.py

class PublicoAlvo(models.Model):
    def __str__(self):
        # Option 1: List all <alvo> fields
        return ", ".join(
            [
                self.alvo1,
                self.alvo2,
            ]
        )

        # Option 2: If you don't like manually listing each <alvo> field
        # return ", ".join(
        #     [
        #         getattr(self, f"alvo{index}") for index in range(1, 3)
        #     ]
        # )

    ...

Это может дать что-то вроде

The value for alvo1, While for alvo2 is this one

Update

Вы также можете попробовать

{% for key, value in servico.alvos.items %}
    {% if key|slice:":4" == "alvo" %}
        {{ value }}<br>
    {% endif %}
{% endfor %}

Это может показать что-то вроде

The value for alvo1
While for alvo2 is this one

Основываясь на первом ответе Ниэля Годфри Понсиано, я смог решить задачу.

models.py:

from djongo import models


class PublicoAlvo(models.Model):
    def __str__(self):
        return ''
    def list(self):
        return [value for key, value in self.__dict__.items() if not key.startswith('_')] 
    alvo1 = models.CharField(max_length = 126)
    alvo2 = models.CharField(max_length = 126, blank = True, default = '')
    class Meta:
        abstract = True

class Servico(models.Model):
    t_id = models.CharField(primary_key = True, unique = True, max_length = 252)
    alvos = models.EmbeddedField(
        model_container = PublicoAlvo
    ) 

А затем я могу перебирать servico.alvos.list, используя for в шаблоне, просто добавив метод list, возвращающий значения соответствующих полей (переменных) в моем классе.

Вернуться на верх