Как получить список со связанными постами, разделенный запятыми, из поля "многие-ко-многим"?

Я пытаюсь изучить Django и столкнулся с проблемой, которую не могу решить до конца. В этом проекте у меня есть приложение под названием projects. В этом приложении у меня есть одна модель под названием Projectinfo и одна под названием Buildingtypes.

Каждый проект может иметь один или несколько типов зданий. Я пытаюсь написать представление, которое перечисляет все проекты со списком связанных с ними типов зданий, разделенных запятыми.

Вот упрощенная версия двух моих моделей:

class Buildingtypes(models.Model):
    buildingtype = models.CharField(max_length=100)

    def __str__(self):
        return self.buildingtype

class ProjectInfo(models.Model):
    project_number = models.CharField(max_length=12, blank=True)
    project_name = models.CharField(max_length=120)
    buildingtypes = models.ManyToManyField(Buildingtypes, default=[1])

    def __str__(self):
        return self.project_name

Я создал представление, которое выглядит следующим образом:

from django.http import HttpResponse
from django.template import loader
from .models import ProjectInfo

def index(request):
    myProjects = ProjectInfo.objects.all()
    template = loader.get_template('projects/index.html')
    context = {
        'projects': myProjects,
        }
    return HttpResponse(template.render(context, request))

А шаблон:

{% if projects %}
    {% for x in projects %}
        {{ x.project_number }} | {{ x.project_name }} | {{ x.buildingtype }}
    {% endfor %}
{% endif %}

В результате получилось следующее:

projectnumber | project name | building type
----------------------------------------------------------
101010        | project 1    | projects.Buildingtypes.None
202020        | project 2    | projects.Buildingtypes.None

Поскольку это явно не удалось, я также попробовал следующее:

{% if projects %}
    {% for x in projects %}
        {{ x.project_number }} | {{ x.project_name }} | {% for y in x.buildingtypes %} {{ y.buildingtype }} {% endfor %}
    {% endfor %}
{% endif %}

В результате получилось следующее:

projectnumber | project name | building type
----------------------------------------------------------
101010        | project 1    | 
202020        | project 2    | 

Я сделал запрос в MySQL, чтобы показать вам, что я ищу. Следующий запрос дает нужный мне результат:

SELECT
    project_number,
    project_name,
    GROUP_CONCAT(pb.buildingtype SEPARATOR ', ') AS buildingtypes
FROM
    projects_projectinfo AS pp
JOIN
    projects_projectinfo_buildingtypes AS ppb
ON
    pp.id = ppb.projectinfo_id
JOIN
    projects_buildingtypes AS pb
ON
    ppb.buildingtypes_id = pb.id
GROUP BY
    pp.id;

Результат:

projectnumber | project name | building type
--------------------------------------------------------------------------------
101010        | project 1    | building type 1, building type 3
202020        | project 2    | building type 2, building type 5, building type 6

Но как преобразовать это в представление?

Я предпринимал различные попытки с помощью select_related, prefetch_related, filter и т.д., но я не могу разобраться с этим.

Любая помощь будет оценена по достоинству.

Вы были очень близки, последняя итерация вашего шаблона должна быть обновлена до:

{% if projects %}
    {% for x in projects %}
        {{ x.project_number }} | {{ x.project_name }} | {% for y in x.buildingtypes.all %} {{ y.buildingtype }} {% endfor %}
    {% endfor %}
{% endif %}

В нем есть доступ к методу all() отношения m2m, загружающему значения, которые вы можете итерировать.

если вы хотите прочитать об этом подробнее: https://docs.djangoproject.com/en/5.0/ref/templates/language/#accessing-method-calls

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