$ python manage.py seed articles --number=20
from rest_framework import serializers
from .models import Article
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id','title')
In [1]: from articles.serializers import ArticleListSerializer
**기본구조확인**
In [2]: serializer = ArticleListSerializer()
In [3]: serializer
Out[3]: ArticleListSerializer():
id = IntegerField(label='ID', read_only=True)
title = CharField(max_length=100)
**Model Instance 객체 확인**
In [4]: article = Article.objects.get(pk=1)
In [5]: article
Out[5]: <Article: Article object (1)>
In [6]: serializer = ArticleListSerializer(article)
In [7]: serializer
Out[7]: ArticleListSerializer(<Article: Article object (1)>):
id = IntegerField(label='ID', read_only=True)
title = CharField(max_length=100)
**QuerySet 객체 전체 확인**
In [8]: articles = Article.objects.all()
In [9]: serializer = ArticleListSerializer(articles,**many=True**)
In [10]: serializer.data
Out[10]: [OrderedDict([('id', 1), ('title', 'Daughter type contain degree he medical.')]),
OrderedDict([('id', 2), ('title', 'Across try industry bring material everybody.')]),
QuerySet 등을 직렬화하기 위해서는 serializer를 인스턴스화 할 때,
many = True를 키워드 인자로 전달해야 한다.
urlpatterns = [
path('articles/',views.article_list),
]
from django.shortcuts import get_list_or_404, render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from .models import Article
from .serializers import ArticleListSerializer
@api_view(['GET'])
def article_list(request):
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles,many=True)
**return Response(**serializer**.**data**)**
from rest_framework import serializers
from .models import Article
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
urlpatterns = [
path('articles/',views.article_list),
path('articles/<int:article_pk',views.article_detail),
]
@api_view(['GET'])
def article_detail(request,article_pk):
**article = get_object_or_404(Article,pk=article_pk)**
serializer = ArticleListSerializer(article)
return Response(serializer.data)
21 번 인스턴스값
from rest_framework import status
@api_view(['GET','POST'])
def article_list(request):
if request.method =='GET': **이부분은 위와 동일**
articles = get_list_or_404(Article)
serializer = ArticleListSerializer(articles,many=True)
return Response(serializer.data)
elif request.method =='POST': **작성부분**
serializer = ArticleListSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data,status=status.HTTP_201_CREATED )
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST )
DRF에는 status code를 보다 명확하고 읽기 쉽게 만드는 데 사용할 수 있는 함수를 제공한다
status=status.HTTP_201_CREATED,
status.HTTP_400_BAD_REQUEST ...
Response(serializer.data,status=201) 와 같이 쓸수도 있지만 DRF는 권장하지 않는다.
title 과 content 적어서 POST 로 제출하기 → 201이면 생성, 400이면 실패
if serializer.is_valid(**raise_exception=True**):
serializer.save()
return Response(serializer.data,status=status.HTTP_201_CREATED )
를 사용하게 되면 오류가 있는경우 알아서 400을 반환한다.
@api_view(['GET','DELETE'])
def article_detail(request,article_pk):
article = get_object_or_404(Article,pk=article_pk)
if request.method =="GET":
serializer = ArticleListSerializer(article)
return Response(serializer.data)
**elif request.method =="DELETE":
article.delete()
data ={
'delete':f'데이터 {article_pk}번이 삭제되었습니다.'
}
return Response(data,status=status.HTTP_204_NO_CONTENT)**
DELETE 버튼이 생겼다
삭제 시 내용이 data 내용으로 바뀐다.
@api_view(['GET','DELETE'**,'PUT'**])
def article_detail(request,article_pk):
...
elif request.method =='PUT':
# serializer = ArticleListSerializer(instance=article,data=request.data)
serializer = ArticleListSerializer(**article,data=request.data**)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
모델 data를 직렬화(serialization)하여 JSON으로 변환
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)
makemigrations -> migrate ->
python manage.py seed articles --number=20
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
path('comments/',views.comment_list)
@api_view(['GET'])
def **comment_list**(request):
comments = get_list_or_404(Comment)
serializer = CommentSerializer(comments,many=True)
return Response(serializer.data)
path('comments/<int:comment_pk>',views.comment_detail)
@api_view(['GET'])
def comment_detail(request,comment_pk):
comment = get_object_or_404(Comment,pk=comment_pk)
serializer = CommentSerializer(comment)
return Response(serializer.data)
path('articles/<int:article_pk>/comments/',views.comment_create),
@api_view(['POST'])
def comment_create(request,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)
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
**read_only_field=('article',)**
@api_view(['GET','DELETE','PUT'])
def comment_detail(request,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()
data ={
'delete':f'댓글 {comment_pk}번이 삭제되었습니다.'
}
return Response(data,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)
class ArticleListSerializer(serializers.ModelSerializer):
**comment_set = serializers.PrimaryKeyRelatedField(many=True,read_only=True)**
class Meta:
model = Article
fields = '__all__'
class Comment(models.Model):
article = models.ForeignKey(Article,on_delete=models.CASCADE,**related_name='comments'**)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
related_name ⇒ 역참조시 생성되는 comment_set을 override 할 수 있음
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields=('article',)
class ArticleListSerializer(serializers.ModelSerializer):
comment_set = **CommentSerializer**(many=True,read_only=True)
class Meta:
model = Article
fields = '__all__'
class ArticleListSerializer(serializers.ModelSerializer):
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__'
→ 필드를 채우는 데 사용할 속성의 이름
→ .count()는 built-in QuerySet API 중 하나