해시 태그 기능을 만들어 보자.

1. 간단한 게시 기능 만들기



구조
mysite
    ├─mysite
    │  └─__pycache__
    ├─post
    │  ├─migrations
    │  │  └─__pycache__
    │  └─__pycache__
    └─templates
mysite/post/models.py
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=20)
    text = models.CharField(max_length=200)

    def __str__(self):
        return self.title
mysite/post/views.py
from django.views.generic import ListView, CreateView
from django.urls import reverse_lazy
from .models import Post


class ListClass(ListView):
    template_name = 'list.html'
    model = Post


class FormClass(CreateView):
    template_name = 'form.html'
    model = Post
    fields = ('title', 'text')
    success_url = reverse_lazy('list')

mysite/post/urls.py
from django.urls import path
from .views import FormClass, ListClass

urlpatterns = [
    path('', ListClass.as_view(), name='list'),
    path('form/', FormClass.as_view(), name='form'),
]

템플릿 파일을 만들기 때문에 settings.py TEMPLATE 설정
'DIRS': [BASE_DIR, 'templates'],
mysite/templates/form.html
<form method="POST">
  {% csrf_token %}
  <p>タイトル<br /><input type="text" name="title" /></p>
  <p>
    内容<br /><textarea type="text" name="text" rows="10" cols="40"></textarea>
  </p>
  <input type="submit" value="投稿する" />
</form>
mysite/templates/list.html
<div class="container">
  {% for post in object_list %}
  <div class="post">
    <p>タイトル<br/>{{ post.title }}</p>
    <p>内容<br/>{{ post.text|linebreaksbr  }}</p>
    <p>--------------------</p>
  </div>
  {% endfor %}
  <div class="form">
    <a href="{% url 'form' %}">新規投稿</a>
  </div>
</div>

출력 결과





2. 태그 기능을 실제로 만들어 간다


mysite/post/models.py
from django.db import models

class Tag(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name


class Post(models.Model):
    title = models.CharField(max_length=20)
    text = models.CharField(max_length=200)
    tag = models.ManyToManyField(Tag)

    def __str__(self):
        return self.title

태그 클래스를 만들고 post 클래스와 연결했습니다.
post 클래스는 많은 태그를 가질 수 있습니다.
mysite/post/views.py
from django.views.generic import ListView, CreateView
from django.urls import reverse_lazy
from django.shortcuts import redirect
from .models import Post, Tag


class ListClass(ListView):
    template_name = 'list.html'
    model = Post


class FormClass(CreateView):
    template_name = 'form.html'
    model = Post
    fields = ('title', 'text')
    success_url = reverse_lazy('list')

    def form_valid(self, form):
        post = Post(
            title=form.cleaned_data["title"], text=form.cleaned_data["text"])
        post.save()
        words = form.cleaned_data["text"].split()
        for word in words:
            if word[0] == "#":
                if Tag.objects.filter(name=word[1:]).exists():
                    tag = Tag.objects.get(name=word[1:])
                else:
                    tag = Tag.objects.create(name=word[1:])
                post.tag.add(tag)
        return redirect('list')

split 안을 지정하지 않는 것으로 공백, 개행등으로 분할을 할 수 있다
분할하여 받은 단어마다 for를 돌린다. 선두 문자가 「#」이면 태그로 간주한다.
「#」이후의 문자의 태그가 존재할지 없는지로, 새롭게 태그를 만들까 분기한다.post.tag.add(tag) 에서 Post 클래스의 tag에 추가한다.

출력 결과



다음과 같은 게시물을 시도합니다.

주) 이전 게시물 내용은 한 번 삭제되었습니다.



게시물에 태그가 등록되었습니다.


태그 클래스도 작성되었습니다.

3. 태그 검색 기능 만들기


mysite/post/views.py
class ListClass(ListView):
    template_name = 'list.html'
    model = Post
    def get_queryset(self):
        tag = self.request.GET.get('tag')

        if tag:
            post_list = Post.objects.filter(
                tag__name__icontains=tag)
        else:
            post_list = Post.objects.all()
        return post_list


ListClass를 조금 편집
filter로 조심해야했던 것이Post.objects.filter(tag__name__icontains=tag)Post의 tag는 ManyToManyField(Tag) 그래서 Tag 클래스의 name으로 검색을 좁혀야 했다.
검색에 대해서는 이전에 기사로 했으므로, 신경이 쓰이는 분은 꼭
간단한 검색 기능을 만들어 보았습니다.
mysite/templates/list.html
<div class="container">
  <form action="" method="get">
    <input name="tag" value="{{ request.GET.tag }}" type="text" />
    <button type="submit">検索する</button>
  </form>
  {% for post in object_list %}
  <div class="post">
    <p>タイトル<br />{{ post.title }}</p>
    <p>内容<br />{{ post.text|linebreaksbr }}</p>
    <p>--------------------</p>
  </div>
  {% endfor %}
  <div class="form">
    <a href="{% url 'form' %}">新規投稿</a>
  </div>
</div>

태그라는 변수에 검색 단어를 넣습니다.

출력 결과



다음과 같은 게시물을 추가해 보았습니다.



"두 번째"로 검색해보십시오.

검색 할 수 있고 단단히 좁혀 있습니다.

마지막으로



이번에는 # 태그로 태그 지정 기능을 만들었습니다. 검색으로 투고를 짜는 곳까지 만들어 보았습니다.
여기에서 태그마다 a 태그 등으로 좁히거나 해도 재미 있다고 생각합니다.
이번에 만들었지만 github

좋은 웹페이지 즐겨찾기