서버를 종료하고 명령어를 입력한다.
pip install django-taggit
pip install django-taggit-templatetags2
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tweet',
'user',
'restaurant',
'taggit.apps.TaggitAppConfig', # 이하를 추가
'taggit_templatetags2',
]
TAGGIT_CASE_INSENSITIVE = True
TAGGIT_LIMIT = 50
우리 TweetModel 안에 django의 tag 서비스를 적용하기.
먼저 태그를 넣을 수 있는 모듈을 설치한다.
# tweet/models.py
from taggit.managers import TaggableManager
TaggableManager
: 글에 태그를 넣을 수 있게 해준다.
class TweetModel(models.Model):
class Meta:
db_table = "tweet"
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
content = models.CharField(max_length=256)
tags = TaggableManager(blank=True) # 추가
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
(blank=True)
비어 있어도 작동하겠다는 의미.
사전 작업이 끝났기 때문에 DB와 migration 해준다.
migrate : 방금 수정한 내용을 DB에 적용한다.
글을 입력할 때 태그를 입력하기 때문에 글을 쓰는 tweet의 POST로 간다.
# tweet/views.py
def tweet(request):
if request.method == 'GET':
user = request.user.is_authenticated
if user:
all_tweet = TweetModel.objects.all().order_by('-created_at')
return render(request, 'tweet/home.html', {'tweet':all_tweet})
else:
return redirect('/sign-in')
elif request.method == 'POST':
user = request.user
content = request.POST.get('my-content', '')
tags = request.POST.get('tag', '').split(',')
# user, content만 있는데 tags를 추가한다.
tags = request.POST.get('tag', '').split(',')
태그를 외부(웹 화면)에서 django 서버로 불러오는 태그다.
해당 태그 목록을 아래와 같이 for문
으로 분리한다.
위 태그는 my_tweet.save()
쪽에서 같이 저장해준다.
if content == '':
all_tweet = TweetModel.objects.all().order_by('-created_at')
return render(request, 'tweet/home.html', {'error':'글은 공백일 수 없습니다.', 'tweet':all_tweet})
else:
my_tweet = TweetModel.objects.create(author=user, content=content)
for tag in tags: # [리스트] 형태. 태그 하나하나를 다시 수정한다.
tag = tag.strip() # 공백을 제거하고 넣어준다.
if tag != '': # 태그가 비어 있지 않다면 (내용이 있다면)
my_tweet.tags.add(tag) # 트윗모델의 태그를 불러서 추가해주는 작업
my_tweet.save()
return redirect('/tweet')
tweet이 완료되었다.
아래는 django taggit으로 검색하면 나오는 공식 document를 일부 수정한 것이다. 그대로 붙여 넣으면 된다.
# tweet/views.py
from django.views.generic import ListView, TemplateView # 추가
# (...)
# tag_cloud_view.html을 보여주겠다.
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
model과 view가 설정되었으니 url을 설정해준다.
# tweet/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('tweet/', views.tweet, name='tweet'),
path('tweet/delete/<int:id>', views.delete_tweet, name='delete-tweet'),
path('tweet/<int:id>', views.detail_tweet, name='detail-tweet'),
path('tweet/comment/<int:id>', views.write_comment, name='write-comment'),
path('tweet/comment/delete/<int:id>', views.delete_comment, name='delete-comment'),
# 이하를 추가한다. 태그로 접근하면 다음 함수가 실행된다.
path('tag/', views.TagCloudTV.as_view(), name='tag_cloud'),
# 태그 내 문자열로 들어가면
path('tag/<str:tag>/', views.TaggedObjectLV.as_view(), name='tagged_object_list'),
]
url과 view 작업을 했고 html이 남았다.
# templates/tweet/home.html
<textarea class="form-control" style="resize: none" name='my-content'
id="my-content"></textarea>
# 이하를 추가한다!
<div class="mt-3 row">
<label for="tag"
class="col-sm-2 col-form-label">이 글의 태그</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="tag" id="tag"
placeholder="콤마(,)로 구분 해 주세요">
</div>
</div>
내 글에 tag가 있으면 보여주겠다.
<h5 class="mt-0">{{ tw.content }}</h5>
# 이하를 추가한다.
{% 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 %}
<h5 class="mt-0">{{ tweet.content }}</h5>
# 이하를 추가한다.
{% if tweet.tags.all %}
{% for tag in tweet.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 %}
{% 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 %}
{% extends "base.html" %}
{% block title %}태그 클라우드{% endblock %}
{% block content %}
<div class="container timeline-container">
<div class="tag-cloud">
{% load taggit_templatetags2_tags %}
{% get_tagcloud as tags %} <!--모든 태그 추출해서 tags변수에 할당-->
{% for tag in tags %}
<a style="text-decoration: none" href="{% url 'tagged_object_list' tag.name %}">
<span class="badge rounded-pill bg-primary">
{{ tag.name }}({{ tag.num_times }})
</span>
</a>
{% endfor %}
</div>
</div>
{% endblock %}