본문 바로가기
Programming/Django

[Django] ManyToManyField 역참조 출력 오류 해결: post.tags 관련 에러 정리

by Mandy's 2025. 7. 23.

Django에서 ManyToManyField를 템플릿에서 출력하려고 할 때 Internal Server Error가 발생했습니다. 

post.tags를 반복문으로 출력하다가 다음과 같은 에러를 만났습니다.

TypeError: 'ManyRelatedManager' object is not iterable

이 오류는 ManyToManyField에 대해 .all()을 호출하지 않고 템플릿에서 직접 루프를 돌리려고 할 때 발생합니다.


문제 상황

예를 들어, 아래와 같은 템플릿 코드가 있다고 가정해봅시다.

<!-- blog/post-detail.html -->
<div>
    {% for tag in post.tags %}
        <span>{{ tag.caption }}</span>
    {% endfor %}
</div>

위 코드는 겉보기에 아무 문제가 없어 보이지만, 실제로는 post.tags는 ManyRelatedManager 객체이며, 직접 반복문을 돌릴 수 없습니다.


해결 방법

Django에서는 .all() 메서드를 명시적으로 호출해서 실제 tag 객체 리스트를 가져와야 합니다.

1. views.py 수정

def post_detail(request, slug):
    identified_post = get_object_or_404(Post, slug=slug)

    return render(request, "blog/post-detail.html", {
        "post": identified_post,
        "post_tags": identified_post.tags.all()  # ✅ 여기가 핵심!
    })

2. post-detail.html 템플릿 수정

<div>
    {% for tag in post_tags %}
        <span class="tag">{{ tag.caption }}</span>
    {% endfor %}
</div>

post_tags를 통해 .all()이 호출된 결과가 템플릿에 안전하게 전달되므로 에러 없이 렌더링됩니다.


마무리 정리

잘못된 코드 올바른 코드

{% for tag in post.tags %} {% for tag in post_tags %}
post.tags (ManyRelatedManager) post.tags.all() (QuerySet)

템플릿에서는 모델의 필드에 직접 .all()을 호출하는 것보다, 뷰에서 미리 데이터를 가공하여 넘겨주는 것이 유지보수와 성능 측면에서도 좋습니다.