
1. 최종 코드를 보시려면 맨 아래에 있습니다.
2. 세팅
- DRF 설치
- https://www.django-rest-framework.org/#installation
- pip install djangorestframework
- settings.py > INSTALLED_APPS 에 'rest_framework', 추가
- 더미데이터를 넣어줄 것 이라면 django seed 설치
- https://github.com/Brobin/django-seed
- pip install django-seed
- settings.py > INSTALLED_APP 에 'django_seed' 추가
- python manage.py seed 앱이름 --number=갯수
3. models.py
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
- models.py는 기존 템플릿으로 만들던 방식과 동일함
- python manage.py makemigrations
- python manage.py migrate
- 기존 articles앱 내의 fixtures폴더 안의 articles.json, comments.json DB에 넣기
- python manage.py loaddata articles.json comments.json
4. 전체 게시글 조회
4.1. serializers.py 만들기
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
4.2. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
]
4.3. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
- 일단 나중의 전체 과정을 위해 편의상 필요한 모듈, 함수 import 해왔음
- serializer의 매개변수는 articles와 many=True 설정
- GET요청만 받도록 데코레이터 지정
4.4. 포스트맨 확인

5. 게시글 생성하기
5.1. serializers.py
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
- 새로운 ArticleSerializer생성, 필드는 '__all__'
5.2. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
# 이 부분 추가!!!!
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
- 생성은 method가 POST
- 유효성 검사하는 함수에 raise_exception=True로 지정해주면 맨 밑에 에러와 400상태를 리턴하는 것 빼줘도 됨
- 유효성 검사를 통과했다면 201상태를 보여줌
5.3. 포스트맨 확인

6. 특정 게시글 조회
6.1. serializers.py
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
6.2. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
]
6.3. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
@api_view(['GET'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
- article_detail 함수 만들어 주기
- article은 article_pk를 받아 쿼리셋을 찾아낸다.
- 이 함수에서 수정과 삭제 기능을 넣어줄 것.
6.4. 포스트맨 확인

7. 데이터 삭제, 수정하기
7.1. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
- 기존 있던 article_detail함수에 메서드 추가, 동작 추가
7.2. 포스트맨 확인


8. 전체 댓글 조회하기
8.1. serializers.py
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
# 이 부분 만들어주기!!
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article',)
- serializers.py에 CommentSerializer클래스 추가
- Meta의 read_only_fields에 article을 넣어준 것은 후에 유효성검사할때 article은 확인 하지 않도록 하기 위함이다.
8.2. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
path('comments/', views.comment_list),
]
8.3. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['GET'])
def comment_list(request):
if request.method == 'GET':
# comments = Comment.objects.all()
comments = get_list_or_404(Comment)
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
- commnet_list 함수 추가
- 기존 모든 게시글을 조회하는 article_list와 비슷함
8.4. 포스트맨 확인

9. 특정 댓글 조회, 수정, 삭제
9.1. serializers.py
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article',)
class ArticleSerializer(serializers.ModelSerializer):
# comment_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
comment_set = CommentSerializer(many=True, read_only=True)
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
class Meta:
model = Article
fields = '__all__'
- CommentSerializers를 ArticleSerializers위로 올려주고,
- ArticleSerializers 에 필드 오버라이드
- comment_set에 CommentSerializer를 참조하고, many=True, read_only=True로 매개변수를 넣어줌
- 댓글의 수를 알고 싶다면 필드 추가
9.2. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
path('comments/', views.comment_list),
path('comments/<int:comment_pk>/', views.comment_detail),
]
9.3. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['GET'])
def comment_list(request):
if request.method == 'GET':
# comments = Comment.objects.all()
comments = get_list_or_404(Comment)
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
# comment = Comment.objects.get(pk=comment_pk)
comment = get_object_or_404(Comment, pk=comment_pk)
if request.method == 'GET':
serializer = CommentSerializer(comment)
return Response(serializer.data)
elif request.method == 'DELETE':
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
- comment_detail함수 추가
- GET은 조회, DELETE는 삭제, PUT은 수정
10. 댓글 생성하기
10.1. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
path('comments/', views.comment_list),
path('comments/<int:comment_pk>/', views.comment_detail),
path('articles/<int:article_pk>/comments/', views.comment_create),
]
10.2. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['GET'])
def comment_list(request):
if request.method == 'GET':
# comments = Comment.objects.all()
comments = get_list_or_404(Comment)
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
# comment = Comment.objects.get(pk=comment_pk)
comment = get_object_or_404(Comment, pk=comment_pk)
if request.method == 'GET':
serializer = CommentSerializer(comment)
return Response(serializer.data)
elif request.method == 'DELETE':
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['POST'])
def comment_create(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=article)
return Response(serializer.data, status=status.HTTP_201_CREATED)
- comment_create함수 추가
- 기존 article생성 하는 것과 비슷하다.
- 이 때의 과정이 유효성 검사를 한 다음에 article을 추가해주는데, 이 부분에서 에러가 난다.
- 그래서 위의 serializers.py에서 read_only_fields에 article을 추가 해준 것이다.
10.3. 포스트맨 확인

11. 최종 코드
11.1. serializers.py
from rest_framework import serializers
from .models import Article, Comment
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content')
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article',)
class ArticleSerializer(serializers.ModelSerializer):
# comment_set = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
comment_set = CommentSerializer(many=True, read_only=True)
comment_count = serializers.IntegerField(source='comment_set.count', read_only=True)
class Meta:
model = Article
fields = '__all__'
11.2. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('articles/', views.article_list),
path('articles/<int:article_pk>/', views.article_detail),
path('comments/', views.comment_list),
path('comments/<int:comment_pk>/', views.comment_detail),
path('articles/<int:article_pk>/comments/', views.comment_create),
]
11.3. views.py
from django.urls import is_valid_path
from articles.serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
from .models import Article, Comment
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.shortcuts import get_object_or_404, get_list_or_404
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
# articles = Article.objects.all()
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'DELETE', 'PUT'])
def article_detail(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
if request.method == 'GET':
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['GET'])
def comment_list(request):
if request.method == 'GET':
# comments = Comment.objects.all()
comments = get_list_or_404(Comment)
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
# comment = Comment.objects.get(pk=comment_pk)
comment = get_object_or_404(Comment, pk=comment_pk)
if request.method == 'GET':
serializer = CommentSerializer(comment)
return Response(serializer.data)
elif request.method == 'DELETE':
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
elif request.method == 'PUT':
serializer = CommentSerializer(comment, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
@api_view(['POST'])
def comment_create(request, article_pk):
# article = Article.objects.get(pk=article_pk)
article = get_object_or_404(Article, pk=article_pk)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(article=article)
return Response(serializer.data, status=status.HTTP_201_CREATED)
'Django 개념' 카테고리의 다른 글
장고 해시태그 기능 구현하기 #해시태그 (0) | 2022.10.13 |
---|---|
장고 팔로우, 팔로잉 기능 구현하기 (1) | 2022.10.13 |
장고 좋아요 기능 구현하기 (0) | 2022.10.13 |
장고 커스텀 filter 만들기 (0) | 2022.10.13 |
Django DB 저장, 조회, 수정, 삭제 crud (장고) (0) | 2022.09.01 |
1. 최종 코드를 보시려면 맨 아래에 있습니다.2. 세팅3. models.py4. 전체 게시글 조회4.1. serializers.py 만들기4.2. urls.py4.3. views.py4.4. 포스트맨 확인5. 게시글 생성하기5.1. serializers.py 5.2. views.py5.3. 포스트맨 확인6. 특정 게시글 조회6.1. serializers.py6.2. urls.py6.3. views.py6.4. 포스트맨 확인7. 데이터 삭제, 수정하기7.1. views.py7.2. 포스트맨 확인8. 전체 댓글 조회하기8.1. serializers.py8.2. urls.py8.3. views.py8.4. 포스트맨 확인9. 특정 댓글 조회, 수정, 삭제9.1. serializers.py9.2. urls.py9.3. views.py10. 댓글 생성하기10.1. urls.py10.2. views.py10.3. 포스트맨 확인11. 최종 코드11.1. serializers.py11.2. urls.py11.3. views.py