파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
인스타그램 서비스에서는 포스팅을 할 때 태그를 지원한다.
django-taggit을 이용하면 이러한 태그 기능을 손쉽게 개발할 수 있다. (django-taggit은 실제 장고 코어 개발자도 참여중인 프로젝트라고 한다.)
본 포스팅에서는 학습을 목표로 하기에 ManyToMany
필드를 이용해 태그 입력을 구현해본다.
from django.db import models
from django.urls import reverse
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
Tag모델을 ManyToMany필드로 추가한다.
extract_tag_list
함수를 통해 caption으로부터 Tag 추출 작업을 수행한다.
from django.conf import settings
from django.db import models
from django.urls import reverse
import re
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
photo = models.ImageField(upload_to='instagram/post/%Y/%m/%d')
caption = models.CharField(max_length=500)
tag_set = models.ManyToManyField('Tag', blank=True)
location = models.CharField(max_length=100)
def __str__(self):
return self.caption
def extract_tag_list(self):
tag_list = []
for tag_name in re.findall(r'#([a-zA-Z\dㄱ-힣]+)', self.caption):
tag, _ = Tag.objects.get_or_create(name=tag_name)
tag_list.append(tag)
return tag_list
# def get_absolute_url(self):
# return reverse('')
모든 필드가 아닌 유저 폼에서 입력받을 폼만 추가한다.
1. tag: 뷰에서 캡션으로 부터 뽑아서 저장 할 것이다.
2. author: 뷰에서 인증 데이터를 확인 후 해당 유저로 저장 할 것이다.
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['photo', 'caption', 'location']
widgets = {
'caption': forms.Textarea
}
post.tag_set.add
: 입력받은 태그 객체 리스트를 모두 해당 post에 대한 태그로 추가한다.
post_tag_set.add를 시작하기 전에 post.save()를 먼저 수행해야 한다. add에 태그 객체 리스트를 입력할 때 post의 pk가 존재해야 하기 때문이다.
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from instagram.forms import PostForm
from instagram.models import Tag
@login_required
def post_new(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user # 유저 저장
post.save() # tag_set에 add하기 전에 수행 (PK가 존재해야 한다.)
post.tag_set.add(*post.extract_tag_list()) # 태그 추가
messages.success(request, '포스팅을 저장했습니다.')
return redirect('/') # TODO: get_absolute_url 활용
else:
form = PostForm()
return render(request, 'instagram/post_form.html', {
'form': form,
})
instagram_post, instagram_tag테이블에는 저장되는 정보가 없다.
다만 instagram_post_tag_set이라는 중간 테이블이 생성된다.
instagram_post_tag_set 테이블은 post_id와 tag_id를 연결해주는 역할을 한다.