다대일 관계 구현하기
Posted on 2021-08-25 by GKSRUDTN99
Django로 웹사이트 만들기
장고
Foreignkey로 Post에 author 필드 구현하기
1. blog/models.py에 author 필드 추가하기
User 모델을 사용해야 하므로 from django.contrib.auth.models import User로 User를 임포트 한다.
User를 이용해 author 필드를 추가한다.
그에 맞게 __str__()
도 수정한다.
#blog/models.py
from django.db import models
from django.contrib.auth.models import User
import os
class Post(models.Model):
title = models.CharField(max_length=30)
hook_text = models.CharField(max_length=100, blank=True)
content = models.TextField()
head_image = models.ImageField(upload_to='blog/images/%Y/%m/%d', blank=True)
file_upload = models.FileField(upload_to='blog/files/%Y/%m/%d', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f'[{self.pk}]{self.title} :: {self.author}'
(...생략...)
2. 마이그레이션하기
3. 사용자가 삭제되어도, Post가 함께 삭제되는 것이 아닌 author 필드만 null이 되게 하기
author 필드를 추가할 때, on_delete=models.CASCADE
대신,
on_delete=models.SET_NULL
을 사용하면 된다.
이때, 해당 필드는 null=True이어야 한다.
포스트 목록 페이지와 포스트 상세 페이지에 author 반영하기
1. 포스트 목록 페이지에 작성자를 추가하도록 테스트 코드 수정
# blog/tests.py
from django.test import TestCase, Client
from bs4 import BeautifulSoup
from .models import Post
# User 모델을 사용해야 하므로 임포트 한다.
from django.contrib.auth.models import User
class TestView(TestCase):
def setUp(self):
self.client = Client()
# 새 유저를 생성해주는 부분
self.user_trump = User.objects.create(username='trump', password='somepassword')
self.user_obama = User.objects.create(username='obama', password='somepassword')
def navbar_test(self, soup):
navbar = soup.nav
self.assertIn('Blog', navbar.text)
self.assertIn('About Me', navbar.text)
logo_btn = soup.find('a', text='Do It Django')
self.assertEqual(logo_btn.attrs['href'],'/')
home_btn = soup.find('a', text='Home')
self.assertEqual(home_btn.attrs['href'], '/')
blog_btn = soup.find('a', text='Blog')
self.assertEqual(blog_btn.attrs['href'], '/blog/')
about_me_btn = soup.find('a', text='About Me')
self.assertEqual(about_me_btn.attrs['href'], '/about_me/')
def test_post_list(self):
response = self.client.get('/blog/')
self.assertEqual(response.status_code, 200)
soup = BeautifulSoup(response.content, 'html.parser')
self.assertEqual(soup.title.text, 'Blog')
self.navbar_test(soup)
self.assertEqual(Post.objects.count(), 0)
main_area = soup.find('div', id='main-area')
self.assertIn('아직 게시물이 없습니다', main_area.text)
# 포스트를 만들 때 author도 추가!
post_001 = Post.objects.create(
title='첫 번째 포스트입니다.',
content='Hello World. We are the world.',
author=self.user_trump,
)
post_002 = Post.objects.create(
title='두 번째 포스트입니다.',
content='1등이 전부는 아니잖아요!',
author=self.user_obama,
)
self.assertEqual(Post.objects.count(), 2)
response = self.client.get('/blog/')
soup = BeautifulSoup(response.content, 'html.parser')
self.assertEqual(response.status_code, 200)
main_area = soup.find('div', id='main-area')
self.assertIn(post_001.title, main_area.text)
self.assertIn(post_002.title, main_area.text)
self.assertNotIn('아직 게시물이 없습니다', main_area.text)
# 아래가 추가된 부분
self.assertIn(self.user_trump.username.upper(), main_area.text)
self.assertIn(self.user_obama.username.upper(), main_area.text)
2. post_list.html에서 작성자의 이름을 표시하도록 수정!
<a href="#">작성자명 들어갈 위치(개발예정)</a>
위 부분을 아래와 같이 수정한다.
<a href="#">{{ p.author | upper }}</a>