Django

[Django] 25. HashTag 기능 만들기(get_or_create(), custom 모델 활용)

개발자 뭄뭄 2022. 11. 4. 21:19
반응형

M:N 관계를 배운 이후에 Hash Tag 기능을 사용하게 되었다.

1. Model에 Hashtag 추가하기

#movies/models.py (main app/models.py)

class Hashtag(models.Model):
    content = models.CharField(max_length=30, unique=True)

class Movie(models.Model):
    ...
    hashtag = models.ManyToManyField(Hashtag, blank=True)
  • 해쉬태그라는 class를 새로 만든다. 그리고 Movie에는 ManyToManyField를 사용해서 hastag field를 추가해 주었다.
💡
unique = True 는 어떤 속성일까?
  • 동일한 해쉬태그의 경우, 복수의 값은 인정하지 않기 위해서 추가한 속성이다.

2. 게시물 저장할 때 hashtag만 따로 받아서 저장하기

#movies/views.py

def create(request):
    if request.method == "POST":
        form = MovieForm(request.POST)
        if form.is_valid():
            movie = form.save(commit=False)
            movie.user = request.user
            movie.save()

            # 해시태그 처리하기
            content = request.POST.get('content')
            c_list = content.split(' ') # 공백으로 분리한다
            
            for c in c_list:
                if "#" in c: # 만약 단어에 #이 붙어있으면 tag로 저장한다.
                    hashtag, created = Hashtag.objects.get_or_create(
                        content = c,
                    )
                    
                    movie_ = Movie.objects.get(pk=movie.pk)
                    movie_.hashtag.add(hashtag)
                    
                        
            return redirect("movies:detail", movie.pk)
    else:
        form = MovieForm()
    context = {
        "form": form,
    }
    return render(request, "movies/create.html", context)
  • movie라는 새로운 데이터를 받을 때, 저장하고 나서 해시태그를 따로 분리해서 저장하는 과정을 거친다. 중간에 (해시태그 처리하기) 부분을 참고한다.
  • 여기에서 .get_or_create 라는 메서드를 처음 사용해 보았는데, 이것은 tuple을 반환한다.
    • 첫번째 인자로는 값을 두번째 인자로는 이미 있는지 혹은 새로만들었는지를 Boolean type으로 반환한다.

3. 각 게시물에서 해시태그는 링크를 포함한 내용으로 다시 만들기

  • 여기에서 사용한 것이 Django Custom Template Filter 였다. (처음 들어봄)

  1. 먼저 지금 작업하고 있는 app 안에 templatetag 라는 이름의 폴더를 만든다.
  1. __init__.py를 작성한다.
  1. 사용자 지정태그 (여기에서는 make_link.py를) 만든다.
  • 사진을 보며 확인해보면 movies/templatetags의 구조를 확인할 수 있다.
# make_link.py

from django import template

register = template.Library()

@register.filter
def add_link(value):
    content = value.content + ' '
    tags = value.hashtag.all()

    # 문자열을 링크가 포함한 문자열로 대체한다.
    for tag in tags:
        content = content.replace(tag.content, f'<a href="/movies/{tag.pk}/hashtag/">{tag.content}</a>')
    return content

  • 이제 새로운 템플릿을 적용할 게시글 html로 가본다.
# movies/templates/detail.html

{% load make_link %}

{% block content %}
  <h2>영화 정보 상세</h2>
  <hr>
  <h3>{{ movie.pk }} 번째 영화 : {{ movie.title }}</h3>
  <br>
  <p>{{ movie|add_link|safe }}</p>
...

  • 상단에 load를 작성해서 템플릿 태그를 불러와 준다.
  • | 를 이용해 필터를 적용하고, safe 필터를 통해 출력 전 추가 HTML ESCAPE 가 필요하지 않은 형태의 문자열로 표시한다.

영화의 상세 페이지로 들어가 보면, 이제 해쉬태그에 링크가 적용된 것을 확인할 수 있다.

4. 해쉬태그를 통한 검색 구현하기

  • 해쉬태그를 눌렀을 때 이동할 경로 설정
    # movies/urls.py
    
    ...
    path("<hashtag_pk>/hashtag/", views.hashtag, name="hashtag"),
    ]
  • 실행할 함수 설정
    # movies/views.py
    
    def hashtag(request, hashtag_pk):
        hashtag = get_object_or_404(Hashtag, pk=hashtag_pk)
        movies = hashtag.movie_set.order_by('-pk')
    
        context = {
            'hashtag':hashtag,
            'movies':movies,
    
        }
        return render(request, "movies/hashtag.html", context)
  • html 파일 설정
    # movies/templates/hashtag.html
    
    {% extends 'base.html' %}
    
    {% block content %}
    
        <h2> {{ hashtag.content }} </h2>
        <p> {{ movies|length }}개의 게시글 </p>
        
        <hr>
        <div>
            <h3>{{ hashtag.content}} (을)를 태그한 글 </h3>
            <br>
            {% for movie in movies %}
                <h3> {{ movie.title }} </h3>
                <p> {{ movie.comment_set.all|length }}개의 댓글 </p>
                <a href="{% url 'movies:detail' movie.pk %}" class="btn-primary btn-sm"> 상세글로 바로가기 </a>
            {% endfor %}
        </div>
    
    
    {% endblock content %}

    최종결과


Uploaded by N2T

반응형

'Django' 카테고리의 다른 글

[Django] 27. View Decorators  (0) 2022.11.04
[Django] 26. “No module named 'bootstrap5’” 오류 해결  (0) 2022.11.04
[Django] 24. M:N 관계  (0) 2022.11.04
[Django] 23. Image Resizing  (0) 2022.11.04
[Django] 22. Image Update  (0) 2022.11.04