티스토리 뷰

● Tag

태그는 views.py , templates를 따로 사용하지 않는다. 왜냐면 태그는 게시물에 추가되는 것이기 때문에 따로 필요하지 않기 때문이다. 앞서 만든 Board 모델, 게시물 작성, 게시물 목록에 태그 내용을 추가해주기만 하면 된다. 추가된 태그 부분은 ### 주석처리하여 표시

 

 

● tag models.py 모델링

from django.db import models

class Tag(models.Model):
    name = models.CharField(max_length=32, verbose_name="태그명")
    registered_date = models.DateTimeField(auto_now_add=True, verbose_name="등록시간")

    def __str__(self):
        return self.name

    class Meta:
        db_table = "community_tag"
        verbose_name = "태그"
        verbose_name_plural = "태그"

태그 클래스에는 태그명과 등록시간을 필드로 추가한다. 이후에는 반드시 python manage.py makemigrations tag, python manage.py migrate tag 를 해야한다.  

 

 

 

● tag admin.py

from django.contrib import admin
from .models import Tag

class TagAdmin(admin.ModelAdmin):
    list_display = ('name', 'registered_date',)

admin.site.register(Tag, TagAdmin)

 

 

● board models.py에 tag 추가하기

from django.db import models

class Board(models.Model):
    title = models.CharField(max_length=64, verbose_name="제목")
    contents = models.TextField(verbose_name="내용")
    registered_date = models.DateTimeField(auto_now_add=True, verbose_name = "등록 시간")
    writer = models.ForeignKey('users.Users', verbose_name = "작성자", on_delete = models.CASCADE)

    ### 태그 추가 부분 ###
    tag = models.ManyToManyField('tag.Tag', verbose_name = "태그")
    
    def __str__(self):
        return self.title

    class Meta:
        db_table = "community_board"
        verbose_name = "게시물"
        verbose_name_plural = "게시물"

- 게시물에 태그 내용을 추가한다. 태그도 작성자와 마찬가지로 다른 app의 모델을 가져오기 때문에 '(app, model이름)' 값을 준다. 하나의 태그는 여러 게시물에 사용될 수 있고, 하나의 게시물에는 여러 개의 태그를 사용할 수 있기 때문에 ManyToManyField를 사용한다. 

 

- board 모델에 새로운 필드 값을 추가한 것이므로 board 앱에 대해서 migrations을 꼭 해야한다.

 

 

 

● board_detail.html, def board_write, BoardForm 에 태그 추가하기

(1) board > forms.py 

- 게시물 작성폼에 태그 필드를 추가한다. 태그는 필수 항목이 아니기 때문에, required 값은 False로 설정한다.

from django import forms

class BoardForm(forms.Form):
    title = forms.CharField(error_messages = {'required':"제목을 입력해주세요"}, label = "제목", max_length=128)
    contents = forms.CharField(error_messages = {'required':"내용을 입력해주세요."}, label = "내용", widget = forms.Textarea)

    ### 태그 추가 부분 ###
    tag = forms.CharField(required = False, label = "태그")

 

(2) board > views.py

- 태그는 게시물이 이미 완성된 상태에서 추가되야 한다. new_board 라는 객체가 생성된 후에 id가 부여되는데 태그는 그 아이디 값을 이용해서 추가되기 때문

 

- 리스트로 받은 태그를 콤마(,)로 구분한다. 

 

- objects.get_or_create 메소드는 두 개의 값을 반환한다. created는 해당 태그가 기존에 있던 태그인지(True) 새로 생성된 태그인지(False) 의 Boolean 값을 반환하고. tag_는 True라면 새로 생성한 태그값이고 False라면 기존의 DB에서 가져온 태그값을 반환한다. 

 

- 이 태그값(tag_)을 앞서 저장한 게시물(new_board)의 tag 필드에 추가한다.

 

- 입력된 태그가 없다면 for문을 벗어난다.

from tag.models import Tag

def board_write(request):
    if not request.session.get('user'):
        return redirect('/users/login')

    if request.method == "GET":
        form = BoardForm()

    elif request.method == "POST":
        form = BoardForm(request.POST)
        if form.is_valid():
            user_id = request.session.get('user')
            user = Users.objects.get(pk = user_id)
            new_board = Board(
                title = form.cleaned_data['title'],
                contents = form.cleaned_data['contents'],
                writer = user
            )
            new_board.save()

            ### 태그 추가 부분 ###
            tags = form.cleaned_data['tag'].split(',')
            for tag in tags:
                if not tag : 
                    continue
                else:
                    tag = tag.strip()
                    tag_, created = Tag.objects.get_or_create(name = tag)
                    new_board.tag.add(tag_)

            return redirect('/board/list')

    return render(request, 'board_write.html', {'form' :form})

 

 

- "태연" " 태연" "태연 " 세 개의 태그는 똑같은 의미인데 양쪽 공백을 제거하지 않으면 세 개의 태그로 구분되어 추가된다. 하지만 태그에 strip() 을 처리하면 하나의 문자열에 양쪽 공백을 제거한 값으로 읽힌다. 오른쪽 사진처럼 게시물을 추가했을 때 왼쪽 사진처럼 "태연" 하나의 태그만 추가된 것을 알 수 있다.

 

 

 

 

(3) templates > board_detail.html 

- board_write.html 은 각 필드에 따라 출력되도록 코드를 작성하여 따로 추가되는 부분은 없고, 게시물을 보여주는 board_detail.html 에서 태그를 보여주는 부분을 추가해야한다. board 객체에서 tag 정보를 모두 가져와서 콤마로 구분해서 출력되도록 한다.

{% extends 'base.html' %}
{% block contents %}

<div class = "row mt-5">
    <div class = "col-12">
        <div class = "form-group">
            <label for = "title">제목</label>
            <input type = "text" class = "form-control" id = "title" value = "{{board.title}}" readonly>

            <label for = "contents">내용</label>
            <textarea class ="form-control" readonly>{{board.contents}}</textarea>

            <!---태그 추가 부분-->
            <labe for = "tags">태그</labe>
            <span id = "tags" class = "form-control">
                {{board.tag.all | join:", "}}
            </span>
        </div>
        <button type = "button" class = "btn btn-primary" onclick = "location.href = '/board/list/'">돌아가기</button>
    </div>
</div>

{% endblock %}

 

- 아래와 같이 board_detail.html 출력된다. 여러 개의 태그를 추가한 경우에 콤마로 구분되어 나타낸 것을 알 수 있다.

 

댓글