전체 페이지뷰

2017년 1월 9일 월요일

Blog 앱, Tag 달기: django-tagging

앞에서 django-tagging을 설치했습니다. 이를 이용해서 블로그 태그 기능을 구현해 봅니다.



설계

UI설계

블로그 post 상세화면(post_detail.html)에 태그를 덧붙이고, 그 태그를 클릭했을 때 나타나는 두 개의 템플릿을 추가로 만들 것입니다.

테이블 설계

포스트 모델 테이블에 tag라는 필드를 하나 추가할 것입니다.
그 tag의 타입은 TagField입니다.

URL설계

URL은 두 개가 추가됩니다.
/blog/tag/ 와 /blog/tag/tagname/으로,
각각 TemplateView, TaggedObjectList라는 제너릭뷰를 상속받아 작성합니다.

코딩

settings.py

django-tagging 패키지를 등록합니다.

(myvenv) D:\myDjango\mysite>subl settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bookmark.apps.BookmarkConfig',
    'blog.apps.BlogConfig',  
    'tagging.apps.TaggingConfig'#추가    
]
cs

mysite 폴더에서 settings.py를 열어 tagging앱을 등록해줍니다.

모델 코딩

블로그 모델 파일을 열어 tag필드를 추가합니다.

(myvenv) D:\myDjango\blog>subl models.py

from __future__ import unicode_literals
from django.utils.encoding import python_2_unicode_compatible
from django.db import models
from django.core.urlresolvers import reverse
from tagging.fields import TagField  #추가
# Create your models here.
@python_2_unicode_compatible
class Post(models.Model):
    title = models.CharField('TITLE', max_length=50)
    slug = models.SlugField('SLUG', unique=True, allow_unicode=True, help_text='one word for title alias.')
    description = models.CharField('DESCRIPTION', max_length=100, blank=True, help_text='simple description text')
    content = models.TextField('CONTENT')
    create_date = models.DateTimeField('Create Date', auto_now_add=True)
    modify_date = models.DateTimeField('Modify Date', auto_now=True)
    tag = TagField() #추가

#하단 동일
cs

tagging으로부터 TagField를 임포트 하고 포스트 컬럼에 tag를 TagField로 정의합니다,
이 TagField는 CharField를 상속받은 것이므로 디폴트로 max_length=255, Blank=True입니다.

테이블의 변화가 생겼으므로 데이터베이스에 반영해야 합니다.

(myvenv) D:\myDjango>python manage.py makemigrations
(myvenv) D:\myDjango>python manage.py migrate
를 입력합니다.

runserver해서 Admin으로 가보면 추가된 사항을 확인 가능합니다.





URLconf 코딩

blog/urls.py에 두 개의 url을 추가합니다.

(myvenv) D:\myDjango\blog>subl urls.py

    # Example: /today/
    url(r'^today/$', PostTAV.as_view(), name='post_today_archive'),
    # Example: /tag/
    url(r'^tag/$', TagTV.as_view(), name='tag_cloud'),
    # Example: /tag/tagname/
    url(r'^tag/(?P<tag>[^/]+(?u))/$', PostTOL.as_view(), name='tagged_object_list'),
    ]
cs

기존 urlpatterns에  아래 두 개의 태그 관련 url을 넣습니다.

View 코딩

blog/views.py에 두개의 클래스형 뷰를 추가합니다.

(myvenv) D:\myDjango\blog>subl views.py

from django.views.generic import ListView, DetailView, TemplateView  #TemplateView 추가
from django.views.generic.dates import ArchiveIndexView, YearArchiveView, MonthArchiveView
from django.views.generic.dates import DayArchiveView, TodayArchiveView
from blog.models import Post
from tagging.models import Tag, TaggedItem #추가
from tagging.views import TaggedObjectList #추가
# Create your views here.
# TemplateView 추가
class TagTV(TemplateView):
    template_name='tagging/tagging_cloud.html'
# ListView
class PostLV(ListView):
    model = Post
    template_name = 'blog/post_all.html'
    context_object_name = 'posts'
    paginate_by = 2
# 추가
class PostTOL(TaggedObjectList):
    model=Post
    template_name='tagging/tagging_post_list.html'
#하단 동일
cs

TemplateView 제너릭뷰를 임포트하고, 
tagging 패키지에서 정의한 모델 두개와, TaggedObjectList 뷰를 임포트합니다.

그리고 TemplateView를 상속받아 TagTV뷰 클래스를 정의하고,
TaggedObjectList를 상속받아 PostTOL 클래스를 정의합니다.


템플릿 코딩

post_detail.html 수정

포스트 글 하단에 태그를 표시하기 위해서는 post_detail.html 수정이 필요합니다.

<div class='body'>
    {{ object.content|linebreaks }}
</div>
<!-- 여기서부터 추가 -->
<div>
<b>TAGS: </b>
{% load tagging_tags %}
{% tags_for_object object as tags %}
{% for tag in tags %}
<a href="{% url 'blog:tagged_object_list' tag.name %}">{{tag.name}}</a>
{% endfor %}
<a href="{% url 'blog:tag_cloud' %}"><i>[ TagCloud ]</i></a>
</div>
<!-- 여기까지 -->
</div>
{% endblock %}
cs


tagging_cloud.html 생성

태그 클라우드란 여러 태그들에 가중치를 부여해서 위치와 글자크기 등으로 리스트를 중요도에 따라 시각화한 것을 말합니다.

이 탬플릿은 blog/templates/tagging/ 디렉토리에 둡니다.

(myvenv) D:\myDjango\blog\templates>mkdir tagging
(myvenv) D:\myDjango\blog\templates>cd tagging
(myvenv) D:\myDjango\blog\templates\tagging>subl tagging_cloud.html

{% extends "base.html" %}
{% block title %}tagging_cloud.html{% endblock %}
{% load staticfiles %}
{% block extrastyle %}{% static "tagging/tag.css" %}{% endblock %}
{% block content %}
<div id="content">
    <h1>Blog Tag Cloud</h1>
    <div class="tag-cloud">
        {% load tagging_tags %}
        {% tag_cloud_for_model blog.Post as tags with steps=6 min_count=1 distribution=log %}
        {% for tag in tags %}
        <span class="tag-{{tag.font_size}}">
            <a href="{% url 'blog:tagged_object_list' tag.name %}">{{tag.name}} ({{tag.font_size}})</a>
        </span>
        {% endfor %}
    </div>
</div>
{% endblock %}
cs

타이틀을 tagging_cloud.html로 지정하고 staticfiles를 로딩합니다.
tag.css는 조금 있다가 작업할 예정입니다.

태그 클라우드 표현방식을 정의합니다. 폰트 크기 범위를 6단계, 폰트 크기 할당 알고리듬을 log로 지정합니다.


tagging_post_list.html

태그가 클릭되었을 때 그 태그가 있는 포스트의 리스트를 보여줍니다.

(myvenv) D:\myDjango\blog\templates\tagging>subl tagging_post_list.html

{% extends "base.html" %}
{% block title %}tagging_post_list.html{% endblock %}
{% block content %}
<div id="content">
    <h1>Posts for tag - {{ tag.name }}</h1>
    {% for post in object_list %}
        <h2><a href='{{ post.get_absolute_url }}'>{{ post.title }}</a></h2>
        {{ post.modify_date|date:"N d, Y" }}
        <p>{{ post.description }}</p>
    {% endfor %}
</div>
{% endblock %}
cs

페이지 제목을 tagging_post_list.html로 정합니다.

PostTOL 믈래스에서 넘겨주는 object_list를 숭회하여 객체릐 title, modify_date, description을 출력합니다.

스타일시트 코딩

blog/static/tagging 폴더를 생성하고 거기에 tag.css 파일을 만듭니다.

(myvenv) D:\myDjango\blog>mkdir static
(myvenv) D:\myDjango\blog>cd static
(myvenv) D:\myDjango\blog\static>mkdir tagging
(myvenv) D:\myDjango\blog\static>cd tagging
(myvenv) D:\myDjango\blog\static\tagging>subl tag.css

.tag-cloud {
    width: 30%;
    margin-left: 30px;
    text-align: center;
    padding: 5px;
    border: 1px solid orange;
    background-color: #ffc;
}
.tag-1 {font-size: 12px;}
.tag-2 {font-size: 14px;}
.tag-3 {font-size: 16px;}
.tag-4 {font-size: 18px;}
.tag-5 {font-size: 20px;}
.tag-6 {font-size: 24px;}
cs

tag-cloud 영역을 지정하고, 크기가 다른 태그 6개를 지정합니다.


이제 지금까지의 작업을 확인하기 위해 runserver하고 Admin에 들어가봅시다.
Post 항목의 +Change 버튼을 누르면 포스트 리스트가 나오는데 그것들을 클릭해서 태그를 입력합니다(콤마로 구분).


다 입력했으면 블로그페이지로 가서 아무 글이나 클릭해봅니다.


하단에 TAGS가 표시되었습니다.
태그를 누르면 그 태그가 달려있는 글의 목록이 나오고,
TagCloud를 누르면 


와 같이 표시됩니다.

이제 작업한 것을 git으로 만들고 github에 올리겠습니다.
git log 해보면...

commit 5b1aec00046a05bf422a9a3749349edc4cd9f462
Author: LateDreamer <xxxxx@xxxx>
Date:   Fri Dec 30 18:18:09 2016 +0900

    Add Homapage base.html

commit ea7006dff52d08164ab907024802b53fa24fc81f
Author: LateDreamer <xxxxxx@xxxx>
Date:   Sat Dec 10 11:17:43 2016 +0900

    My Django Initial commit

아직 두번밖에 커밋하지 않았군요. 아무래도 버릇이 되지 않다보니 자꾸만 잊게 됩니다.

좀 더 자주하는 습관을 들여야 하겠습니다.

댓글 없음:

댓글 쓰기