0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ハッシュタグ機能を作ってみよう

Last updated at Posted at 2021-07-04

###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'),
]

templatesファイルを作るので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>

####出力結果
スクリーンショット 2021-07-04 162732.png

###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

tagクラスを作り、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に追加する。

####出力結果
#####次のような投稿をしてみる
注)前の投稿内容は一度削除しました
スクリーンショット 2021-07-04 221433.png

スクリーンショット 2021-07-04 221505.png
投稿にタグが登録されました

スクリーンショット 2021-07-04 221522.png
タグのクラスも作成されました

###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>

tagという変数に検索ワードを入れる

####出力結果
#####次のような投稿を追加してみた
スクリーンショット 2021-07-04 224109.png

「2回目」と検索してみる
スクリーンショット 2021-07-04 224146.png
検索出来てしっかり絞り込めています

###最後に

今回は#タグでタグ付けの機能を作りました。検索で投稿を絞るところまで作ってみました。
ここから、タグごとにaタグなどで絞り込んだりしてみても面白いなと思います。
今回作ったもののgithub

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?