Django 06

·2023년 9월 2일
0

파이썬

목록 보기
10/18

태그 달기

장고로 트윗에 태그를 달아주는 작업을 하던 도중 궁금한 점이 생겼다.
tweet 과 관련된 모델이니 tweet의 models.py/TweetModel 에 tags = TaggableManager(blank=True) 을 추가해주고 views.py에 Tag 관련 클래스들을 추가해줬다.

tweet/views.py

# import ...
from taggit.managers import TaggableManager
from django.views.generic import ListView, TemplateView
# generic 모델은 명시된 모든 모델(TweetModel)을 가져오기 위해 데이터베이스를 쿼리


class TagCloudTV(TemplateView):
    template_name = 'taggit/tag_cloud_view.html'

class TaggedObjectLV(ListView):
    template_name = 'taggit/tag_with_post.html'
    model = TweetModel()

    def get_queryset(self):
        return TweetModel.objects.filter(tags__name=self.kwargs.get('tag'))

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['tagname'] = self.kwargs['tag']
        return context

여기서 generic 모델이란 무엇이고, get_context_data() 는 무엇인가?

우선 generic 은 장고에서 기본적으로 제공하는 클래스이다. 데이터베이스에 있는 데이터들을 보여줄 때 사용하기 좋으며 generic display view 에는 ListView, DetailView, TemplateView 등이 있다. 자세한 상속 관계와 사용 예시는 여기

위의 코드에서는 ListView 를 사용하며 template_name 으로 어떤 html 을 사용할 것인지 알려주었다. (속성이 없다면 장고가 모델 이름에서 유추하여 모델이름_list.html 을 찾아내 보여준다.)

model = TweetModel() 을 통해 object_list 의 형태로 TweetModel() 객체가 전달될 것임을 알 수 있다.

이 다음 get_context_data() 를 재정의하여 {'tagname' : tag} 의 형태로 데이터를 return 하여 준다.

templates/taggit/tag_with_post.html

{% extends "base.html" %}

{% block title %}태그 글 리스트{% endblock %}

{% block content %}

    <div class="container">
        <h3 class="mt-2">Posts for tag - {{ tagname }}</h3>
        <hr>
        <div class="card">
            <div class="card-body">
                {% for tweet in object_list %}
                    <h4>
                        <a href="/tweet/{{ tweet.id }}">{{ tweet.content }}</a>
                    </h4>
                    {{ tweet.updated_at|timesince}}
                    <p> {{ tweet.author }}</p>
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}

이후 home.html 과 tweet_detail.html 의 textbox div 에

											{% if tw.tags.all %}
                                                {% for tw in tw.tags.all %}
                                                    <a style="text-decoration: none"
                                                       href="{% url 'tagged_object_list' tag.name %}">
                                                    <span class="badge rounded-pill bg-success">
                                                        {{ tag.name }}
                                                    </span>
                                                    </a>
                                                {% endfor %}
                                                -<a style="text-decoration: none"
                                                    href="{% url 'tag_cloud' %}">TagCloud</a>
                                            {% endif %}

이걸 추가해줬는데
Reverse for 'tagged_object_list' with arguments '('',)' not found. 1 pattern(s) tried: ['tag/(?P[^/]+)\Z']
이런 에러가 뜨는 것이다. 찾아봤더니 전달되어야할 id 값이 제대로 전달되지 않았을 때 나는 에러라고 한다.

그리고 다시 보니... tag 라고 적었어야 할 for 문을 너무 자연스럽게 tw 라고 적어놨었다... ㅠㅠ

{% if tw.tags.all %}
                                            {% for tag in tw.tags.all %}
                                                <a style="text-decoration: none"
                                                   href="{% url 'tagged_object_list' tag.name %}">
                                                    <span class="badge rounded-pill bg-success">
                                                        {{ tag.name }}
                                                    </span>
                                                </a>
                                            {% endfor %}
                                            -<a style="text-decoration: none"
                                                href="{% url 'tag_cloud' %}">TagCloud</a>
                                        {% endif %}

수정 결과

잘 출력된다!

profile
공부 중

2개의 댓글

comment-user-thumbnail
2023년 9월 5일

ListView의 사용법을 익히셨군요! 오류도 잘 해결되어서 다행입니다~!

1개의 답글