# 게시판 기능 만들기 준비
오늘은 게시판 기능을 만들 것이다.
posts branch로 새롭게 이동해서 작업해주기~
이제 posts app을 만들고 settings.py에 추가한다.
# bash
python manage.py startapp posts
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt',
"accounts",
"posts",
]
# urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls')),
path('posts/', include('posts.urls')),
]
urls.py에도 미리 추가하기.
# 모델 만들기
from django.db import models
from accounts.models import User
import uuid
# Create your models here.
class Post(models.Model):
level_list = [
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5)
]
group_list = [
('진로', '진로'),
('연애', '연애'),
('가족/친구', '가족/친구'),
('기타', '기타')
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, null=True, on_delete=models.CASCADE) # 게시글 작성자
level=models.IntegerField(choices=level_list) # 심각도
title = models.CharField(max_length=20)
tag = models.CharField(max_length=8)
group = models.CharField(max_length=16, choices=group_list) # 게시판 유형
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'[{self.id}]{self.title} :: {self.author}'
author는 외부 키 User 모델을 참조하도록 했다.
# serializers.py
from rest_framework import serializers
from .models import *
class PostSerializer(serializers.ModelSerializer):
author = serializers.ReadOnlyField(source='author.nickname')
class Meta:
model = Post
fields = ['id', 'author','level','title','tag','group','content','created_at','updated_at']
serializer에서 크게 수정할 부분은 없어 '__all__' 로 필드를 전부 가져오려고 했는데 작성자 추가해야 했다.
'__all__' 에 author 필드만 추가하는 기능은 없을라나
# views.py + urls.py + permissions.py
from .serializers import *
from .permissions import AuthenticatedOnly
from rest_framework.permissions import IsAuthenticated
from rest_framework import viewsets, filters
# Create your views here.
class PostViewSet(viewsets.ModelViewSet):
queryset=Post.objects.all()
serializer_class=PostSerializer
# filter_backends = [filters.SearchFilter] 검색 기능 미정
# search_fields = ['content', 'user__nickname']
permission_classes = [IsAuthenticated, AuthenticatedOnly]
def perform_create(self, serializer):
serializer.save(author = self.request.user)
view도 serializer와 queryset을 지정하면 CRUD 기능을 전부 만들어주는 ModelViewSet을 이용하여 아주 간단하게 만들어 주었다.
우리 기능은 이게 핵심이 아니기 때문에...
perfom_create() 메소드를 가져와서 author 필드에 작성자 정보가 들어가도록 수정해준다.
또 내가 알기로는 permission에서 설정된대로 했을 때, 작성자가 아니여도 아무나 게시글을 삭제할 수 있다.
이를 방지하기 위해 새로운 권한을 만들어준다.
from rest_framework import permissions
class AuthenticatedOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# 읽기 권한 요청이 들어오면 허용
if request.method in permissions.SAFE_METHODS:
return True
# 요청자(request.user)가 객체(Blog)의 user와 동일한지 확인
return obj.author == request.user
즉, django에 기본 내장된 IsAuthenticated로 인해 인증된 사용자만 CRUD 요청이 가능하다.
또, SAFE Method(put, patch, delete 등)에 해당하는 기능은 작성자와 로그인한 유저가 같아야지 가능하다.
from django.urls import path, include
from .views import *
from django.conf.urls.static import static
from .views import *
from rest_framework.routers import DefaultRouter
app_name = 'posts'
router = DefaultRouter()
router.register('post', PostViewSet) #comment list볼러면 설정해줘야함..
urlpatterns = [
path('', include(router.urls)),
]
ModelVierSet을 이용할때는 Router에 직접 url을 지정하는..저런 식으로 해주어야 한다.
이제 여기까지 완료됐으면 migrations + migrate 후 runserver
# 확인
잘 되는 것 같지만 인증이 되지 않아서 웹 브라우저는 안됨
따로 앱을 이용하여 로그인 후 이용해준다.
get 외에도 세부 게시글의 get, put, patch, delete 등 여러 기능들이 잘 되는 것을 확인했다.
# API 명세서
posts는 권한까지 생각하고 세부 게시글까지 get할 수 있어서 .이것저것 작성할게 많다.
일단 url이랑 기능 설명만 작성해야지.
댓글까지 구현해야 해서 나중에 수정하기 힘들당...
'졸업 프로젝트' 카테고리의 다른 글
pagination 추가하기 + 배포 준비 (0) | 2024.02.16 |
---|---|
게시판 댓글 기능 (0) | 2024.02.03 |
[Django] Direct assignment to the forward side of a many-to-many set is prohibited. Use groups.set() instead. (0) | 2024.01.31 |
유저 수정 기능 + API 명세서 작성 (0) | 2024.01.29 |
Django 기초 + 유저 기능 만들기 (1) | 2024.01.28 |