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)댓글 목록 조회를 위한 CommentSerializer
from .models import Article, Comment
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
url 작성
urlpatterns = [
path('comments/', views.comment_list),
]
view 함수 작성
from .models import Article, Comment
from .serializers import ArticleListSerializer, ArticleSerializer, CommentSerializer
@api_view(['GET'])
def comment_list(request):
comments = Comment.objects.all()
serializer = CommentSerializer(comments, many=True)
return Response(serializer.data)
단일 댓글 조회를 위한 url 및 view 함수 작성
# articles/urls.py
urlpatterns = [
...,
path('comments/<int:comment_pk>/', views.comment_detail),
]
# articles/views.py
@api_view(['GET'])
def comment_detail(request, comment_pk):
comment = Comment.objects.get(pk=comment_pk)
serializer = CommentSerializer(comment)
return Response(serializer.data)
단일 댓글 생성을 위한 url 및 view 함수 작성
# articles/urls.py
urlpatterns = [
...,
path('comments/<int:article_pk>/comments/', views.comment_create),
]
# articles/views.py
@api_view(['GET'])
def comment_create(request, article_pk):
article = Article.objects.get(pk=article_pk)
serializer = CommentSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
serializer 인스턴스의 save() 메서드는 특정 serializer 인스턴스를 저장하는 과정에서 추가 데이터를 받을 수 있음
# articles/views.py
@api_view(['GET'])
def comment_create(request, article_pk):
article = Article.objects.get(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)
데이터를 전송 받은 시점에 유효성 검사에서 제외시키고, 데이터 조회시에는 출력 하는 필드
# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('articles',
)
단일 댓글 삭제 및 수정을 위한 view 함수 작성
# articles/views.py
@api_view(['GET', 'DELETE', 'PUT'])
def comment_detail(request, comment_pk):
comment = Comment.objects.get(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)
댓글 조회 시 게시글 번호만 제공해주는 것이 아닌 '게시글의 제목'까지 제공하기
필요한 데이터를 만들기 위한 serializer는 내부에서 추가 선언이 가능
# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
class ArticleTitleserializer(serializers.Modelserializer):
class Meta:
model = Article
fields = ('title',)
article = ArticleTitleserializer(read_only=True)
class Meta:
model = Comment
fields = '__all__'
Nested realtionships (역참조 매니저 활용)
모델 관계 상으로는 참조하는 대상은 참조되는 대상의 표현에 포함되거나 중첩될 수 있음
이러한 중첩된 관계는 serializers를 필드로 사용하여 표현 가능
# articles/serializers.py
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = '__all__'
read_only_fields = ('article',)
class ArticleSerializer(serializers.Modelserializer):
comment_set = CommentSerializer(many = True, read_only = True)
class Meta:
model = Article
fields = ('title',)
'source' argument
필드를 채우는 데 사용할 속성의 이름
점 표기법을 사용하여 속성을 탐색 할 수 있음
# articles/serializers.py
class ArticleSerializer(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 = ('title',)
특정 필드를 override 혹은 추가한 경우 read_only_fields는 동작하지 않음
이런 경우 새로운 필드에 read_only 키워드 인자로 작성해야함
# articles/serializers.py
class ArticleSerializer(serializers.Modelserializer):
comment_set = CommentSerializer(many = True)
comment_count = serializers.IntegerField(source = 'comment_set.count')
class Meta:
model = Article
fields = '__all__'
read_only_fields = ('comment_set', 'comment_count')
DRF 위한 OpenAPI 3.0 구조 생성을 도와주는 라이브러리
설치 및 등록
pip install drf-spectacular
# settings.py
INSTALLED_APPS = [
...,
'drf_spectacular',
]
관련 설정 코드 입력(OpenAPI 구조 자동 생성 코드)
# settings.py
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
# drf/urls.py
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
urlpatterns = [
path("admin/", admin.site.urls),
path('api/v1/', include('articles.urls')),
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
path('api/schema/swagger-ui/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
path('api/schema/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]
```