drf ๋ฐฑ์๋๊ฐ๋ฐ + ํ๋ก ํธ๊ฐ๋ฐ
: ์ด๋ฒ ํ๋ก์ ํธ๋ ํํ๋ก์ ํธ๋ก ์์ํฉ๋๋ค.
* front ๊ฐ๋ฐ
mypage.html
* back ๊ฐ๋ฐ
datetime ํ์ ๋ณ๊ฒฝ (์ฐ์์ผ์๊ฐ)
# 'DATETIME_FORMAT' ์ถ๊ฐ
REST_FRAMEWORK = {
'DATETIME_FORMAT': "%Y/%m/%d %H:%M",
'DEFAULT_PERMISSION_CLASSES': [ # ๊ธฐ๋ณธ์ ์ธ view ์ ๊ทผ ๊ถํ ์ง์
'rest_framework.permissions.AllowAny'
],
'DEFAULT_AUTHENTICATION_CLASSES': [ # session ํน์ token์ ์ธ์ฆ ํ ํด๋์ค ์ค์
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PARSER_CLASSES': [ # request.data ์์ฑ์ ์ก์ธ์ค ํ ๋ ์ฌ์ฉ๋๋ ํ์ ์ง์
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE':2,
}
models.py
from django.db import models
from user.models import User
class ArticleLike(models.Model):
like_category = models.CharField("๊ณต๊ฐ์ข
๋ฅ", max_length=50, default="")
class CommentLike(models.Model):
like_category = models.CharField("๊ณต๊ฐ์ข
๋ฅ", max_length=50, default="")
class Vote(models.Model):
category = models.CharField("๊ณต๊ฐ์ข
๋ฅ", max_length=50, default="")
class Article(models.Model):
article_author = models.ForeignKey('user.User', verbose_name="์์ฑ์", on_delete=models.CASCADE)
board = models.ForeignKey('Board', verbose_name="ํด๋น ๊ฒ์ํ", on_delete=models.CASCADE)
article_category = models.ForeignKey('Category', verbose_name="์นดํ
๊ณ ๋ฆฌ ์ข
๋ฅ", on_delete=models.CASCADE, null=True)
article_title = models.CharField('๊ฒ์๋ฌผ ์ ์ฅ', max_length=50)
article_contents = models.TextField('๊ฒ์๋ฌผ ๋ด์ฉ', max_length=500)
article_image = models.ImageField('์ด๋ฏธ์ง', upload_to="", blank=True)
article_post_date = models.DateField('๊ฒ์ ์ผ์', auto_now_add=True)
article_exposure_date = models.DateField('๊ฒ์ ๋ง๋ฃ ์ผ์', blank=True)
article_like = models.ManyToManyField(ArticleLike, through='ArticleLikeBridge')
article_vote = models.ManyToManyField(Vote, through='ArticleVoteBridge')
def __str__(self):
return f"{self.article_author.username} ๋์ด {self.board}์ {self.article_category}ํ๊ทธ๋ก ์์ฑํ ๊ธ์
๋๋ค."
class Comment(models.Model):
comment_author = models.ForeignKey('user.User', verbose_name="์ฌ์ฉ์", on_delete=models.CASCADE)
article = models.ForeignKey(Article, verbose_name="๊ฒ์๊ธ", on_delete=models.CASCADE)
comment_contents = models.TextField("๋ด์ฉ", max_length=100)
comment_created_at = models.DateTimeField("์์ฑ์๊ฐ", auto_now_add=True,)
comment_updated_at = models.DateTimeField("์์ ์๊ฐ",auto_now = True,)
comment_like = models.ManyToManyField(CommentLike, through='CommentLikeBridge')
def __str__(self):
return f"{self.comment_author.username} ๋์ด ์์ฑํ์ ๋๊ธ์
๋๋ค."
class Board(models.Model):
name = models.CharField("๊ฒ์ํ ์ด๋ฆ", max_length=50, default="")
def __str__(self):
return f"{self.name}"
class Category(models.Model):
name = models.CharField("๊ฒ์๊ธ ์นดํ
๊ณ ๋ฆฌ ์ด๋ฆ", max_length=50, default="")
def __str__(self):
return f"{self.name}"
class ArticleLikeBridge(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
like = models.ForeignKey(ArticleLike, on_delete=models.CASCADE, null=True)
category = models.CharField("๊ฒ์๊ธ ๊ณต๊ฐ ์นดํ
๊ณ ๋ฆฌ ์ด๋ฆ", max_length=50, default="")
class ArticleVoteBridge(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
vote = models.ForeignKey(Vote, on_delete=models.CASCADE, null=True)
category = models.CharField("๊ฒ์๊ธ ํฌํ ์นดํ
๊ณ ๋ฆฌ ์ด๋ฆ", max_length=50, default="")
class CommentLikeBridge(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.ForeignKey(Comment, on_delete=models.CASCADE)
like = models.ForeignKey(CommentLike, on_delete=models.CASCADE, null=True)
category = models.CharField("์ฝ๋ฉํธ ๊ณต๊ฐ ์นดํ
๊ณ ๋ฆฌ ์ด๋ฆ", max_length=50, default="")
serializers.py
from rest_framework import serializers
from article.models import (
Article as ArticleModel,
Comment as CommentModel,
CommentLikeBridge,
ArticleVoteBridge,
)
from user.models import User as User
from user.serializers import UserSerializer
class CommentSerializer(serializers.ModelSerializer):
comments_related_article = serializers.SerializerMethodField()
author = serializers.SerializerMethodField()
count = serializers.SerializerMethodField()
def get_comments_related_article(self,obj):
return obj.article.id
def get_author(self,obj):
return obj.comment_author.username
def get_count(self,obj):
like_count = CommentLikeBridge.objects.filter(comment_id=obj.id).count()
return like_count
# custum update
def update(self, instance, validated_data):
for key, value in validated_data.items():
if key == "comment_author":
instance.user(value)
continue
setattr(instance, key, value)
instance.save()
return instance
class Meta :
model = CommentModel
fields = ['id', 'article', 'author', 'comment_created_at', 'comment_contents', 'comments_related_article', 'count']
class ArticleSerializer(serializers.ModelSerializer):
comment_set = CommentSerializer(many=True)
author = serializers.SerializerMethodField()
category = serializers.SerializerMethodField()
vote = serializers.SerializerMethodField()
def get_category(self,obj):
return obj.article_category.name
def get_author(self,obj):
return obj.article_author.username
def get_vote(self,obj):
votes = ArticleVoteBridge.objects.filter(article_id=obj.id)
votes = list(votes.values())
vote_count = dict(fox=0, green=0, miss=0)
for vote in votes:
if vote['category'] == 'ํญ์ค์
๋๋ค':
vote_count['fox'] += 1
elif vote['category'] == '๊ทธ๋ฆฐ๋ผ์ดํธ':
vote_count['green'] += 1
else:
vote_count['miss'] += 1
return vote_count
# custum update
def update(self, instance, validated_data):
for key, value in validated_data.items():
if key == "article_author":
instance.set_author(value)
continue
setattr(instance, key, value)
instance.save()
return instance
class Meta:
model = ArticleModel
fields = ['id','author','article_title','category','article_image', 'board', 'vote',
'article_contents','article_post_date',
'article_exposure_date','comment_set'
]
views.py
from unicodedata import category
from rest_framework.pagination import LimitOffsetPagination
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import permission_classes
from rest_framework_simplejwt.authentication import JWTAuthentication
from article.models import (
Article as ArticleModel,
Comment as CommentModel,
Board as BoardModel,
Category as CategoryModel,
ArticleLike,
CommentLike,
CommentLikeBridge,
ArticleLikeBridge,
ArticleVoteBridge,
Vote as VoteModel
)
from article.serializers import (
ArticleSerializer,
CommentSerializer,
)
# ๊ฒ์๊ธ ํ์ด์ง๋ค์ด์
๋ฆฌ์คํ
class ArticlePagination(APIView, LimitOffsetPagination):
def get(self, request, format=None):
articles = ArticleModel.objects.all()
results = self.paginate_queryset(articles, request, view=self)
serializer = ArticleSerializer(results, many=True)
return self.get_paginated_response(serializer.data)
# ๋๊ธ ํ์ด์ง๋ค์ด์
๋ฆฌ์คํ
class CommentPagination(APIView, LimitOffsetPagination):
def get(self, request, format=None):
comments = CommentModel.objects.all()
results = self.paginate_queryset(comments, request, view=self)
serializer = CommentSerializer(results, many=True)
return self.get_paginated_response(serializer.data)
class ArticleView(APIView):
permission_classes = [permissions.AllowAny]
# ๋ชจ๋ ๊ฒ์๊ธ ๋ฆฌ์คํ
def get(self, request):
articles = list(ArticleModel.objects.all().order_by("-id"))
result = ArticleSerializer(articles, many=True).data
return Response(result)
# ๊ฒ์๊ธ ์์ฑ
def post(self, request):
if request.user.is_anonymous:
return Response({"error":"๊ธ ์์ฑ์ ์ํด ๋ก๊ทธ์ธ์ ํด์ฃผ์ธ์."})
else:
board = BoardModel.objects.get(name=request.data.get('board'))
category = CategoryModel.objects.get(name=request.data.get('article_category'))
article = ArticleModel.objects.create(
article_author = request.user,
article_title = request.data.get('article_title',''),
article_contents = request.data.get('article_contents',''),
article_image = request.FILES,
article_exposure_date = request.data.get('article_exposure_date',''),
board = board,
article_category = category,
)
if len(request.data.get('article_title','')) <= 1 :
return Response({"error":"title์ด 1์ ์ดํ๋ผ๋ฉด ๊ฒ์๊ธ์ ์์ฑํ ์ ์์ต๋๋ค."})
elif len(request.data.get('article_contents','')) <= 10 :
return Response({"error":"contents๊ฐ 10์ ์ดํ๋ผ๋ฉด ๊ฒ์๊ธ์ ์์ฑํ ์ ์์ต๋๋ค."})
else:
article.save()
return Response({"message":"๊ฒ์๋ฌผ ์์ฑ ์๋ฃ!!"})
# ๊ฒ์๋ฌผ ์
๋ฐ์ดํธ
def put(self, request, obj_id):
article = ArticleModel.objects.get(id=obj_id)
if request.user == article.article_author or request.user.is_admin:
article_serializer = ArticleSerializer(article, data=request.data, partial=True, context={"request": request})
if article_serializer.is_valid():
article_serializer.save()
return Response(article_serializer.data, status=status.HTTP_200_OK)
else:
return Response(article_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response({"message":"๊ฒ์๊ธ ์์ ์ ๊ฒ์๊ธ ์์ฑ์๋ง ํ ์ ์์ต๋๋ค."})
# ๊ฒ์๋ฌผ ์ญ์
def delete(self, request, obj_id):
article = ArticleModel.objects.get(id=obj_id)
title = article.article_title
user = article.article_author
if request.user == article.article_author or request.user.is_admin:
ArticleModel.objects.get(id=obj_id).delete()
return Response({'message': f'{user}๋์ {title} ๊ฒ์๊ธ์ด ์ญ์ ๋์์ต๋๋ค.'})
else:
return Response({"message":"๊ฒ์๊ธ ์ญ์ ๋ ๊ฒ์๊ธ ์์ฑ์๋ง ํ ์ ์์ต๋๋ค."})
# article detail ํ์ด์ง article/<obj_id>/detail/
class ArticleDetailView(APIView):
def get(self, request, obj_id):
article = ArticleModel.objects.get(id=obj_id)
return Response(ArticleSerializer(article).data)
class CommentView(APIView):
def get(self, request, obj_id):
return Response(CommentSerializer(obj_id).data)
# ๋๊ธ ์์ฑ
def post(self, request, obj_id):
if request.user.is_anonymous:
return Response({"error":"๋๊ธ ์์ฑ์ ์ํด ๋ก๊ทธ์ธ์ ํด์ฃผ์ธ์."})
else:
user = request.user
request.data['article'] = ArticleModel.objects.get(id=obj_id)
contents = request.data.get('comment_contents','')
comment = CommentModel(
article = request.data['article'],
comment_author = user,
comment_contents = contents,
)
comment.save()
return Response({"message":"๋๊ธ ์์ฑ ์๋ฃ!"})
# ๋๊ธ ์
๋ฐ์ดํธ
def put(self, request, obj_id):
data = request.data
comment = CommentModel.objects.get(id=obj_id)
if request.user == comment.comment_author or request.user.is_admin:
comment_serializer = CommentSerializer(comment, data, partial=True, context={"request": request})
if comment_serializer.is_valid():
comment_serializer.save()
return Response(comment_serializer.data, status=status.HTTP_200_OK)
else:
return Response({"error":"๋๊ธ ์์ ์ ๋๊ธ ์์ฑ์๋ง ๊ฐ๋ฅํฉ๋๋ค."})
# ๋๊ธ ์ญ์
def delete(self, request, obj_id):
comment = CommentModel.objects.get(id=obj_id)
comment_author = comment.comment_author
article_author = comment.article.article_author
if request.user == comment.comment_author or request.user.is_admin or request.user == article_author:
CommentModel.objects.get(id=obj_id).delete()
return Response({'message': f'{comment_author}๋์ ๋๊ธ์ด ์ญ์ ๋์์ต๋๋ค.'})
else:
return Response({'error': '๋๊ธ ์ญ์ ๊ถํ์ด ์์ต๋๋ค'})
# ๊ฒ์๊ธ ๊ณต๊ฐ
class ArticleLikeView(APIView):
authentication_classes = [JWTAuthentication]
def post(self, request, article_id):
like = ArticleLike.objects.create()
article_title = ArticleModel.objects.get(id=article_id)
all = list(ArticleLikeBridge.objects.all().values())
print(all)
all_id = []
for obj in all:
all_id.append(obj['user_id'])
if request.user.id in all_id:
article_like = ArticleLikeBridge.objects.get(user_id=request.user.id)
article_like.delete()
return Response({'message': f'{request.user}๋๊ป์ {article_title.article_title}์ ๊ณต๊ฐ์ ์ทจ์ํ์
จ์ต๋๋ค.'})
else:
article_like = ArticleLikeBridge(
article_id = article_id,
user_id = request.user.id,
like_id = like.id,
category = request.data.get('category')
)
article_like.save()
return Response({'message': f'{request.user}๋๊ป์ {article_title.article_title}์ {article_like.category}ํ์
จ์ต๋๋ค.'})
# ๊ฒ์๊ธ ํฌํ
class ArticleVoteBridgeView(APIView):
authentication_classes = [JWTAuthentication]
# ๊ฒ์๊ธ ํฌํ ์นด์ดํธ
def get(self, request, article_id):
votes = ArticleVoteBridge.objects.filter(article_id=article_id)
votes = list(votes.values())
count = dict(fox=0, green=0, miss=0)
for vote in votes:
if vote['category'] == 'ํญ์ค์
๋๋ค':
count['fox'] += 1
elif vote['category'] == '๊ทธ๋ฆฐ๋ผ์ดํธ':
count['green'] += 1
else:
count['miss'] += 1
return Response(count)
def post(self, request, article_id):
vote = VoteModel.objects.create()
article_title = ArticleModel.objects.get(id=article_id)
all = list(ArticleVoteBridge.objects.all().values())
all_id = []
for obj in all:
all_id.append(obj['user_id'])
if request.user.id in all_id:
article_vote = ArticleVoteBridge.objects.get(user_id=request.user.id)
article_vote.delete()
return Response({'message': f'{article_vote.category} ํฌํ ์ทจ์..'})
else:
article_vote = ArticleVoteBridge(
article_id = article_id,
user_id = request.user.id,
vote_id = vote.id,
category = request.data.get('category',"")
)
article_vote.save()
return Response({'message': f'{article_vote.category}์ ํํ!'})
# ๋๊ธ ๊ณต๊ฐ
class CommentLikeView(APIView):
authentication_classes = [JWTAuthentication]
# ๋๊ธ ๊ณต๊ฐ ์นด์ดํธ
def get(self, request, comment_id):
like_count = CommentLikeBridge.objects.filter(comment_id=comment_id).count()
return Response(like_count)
def post(self, request, comment_id):
like = CommentLike.objects.create()
comment = CommentModel.objects.get(id=comment_id)
contents = comment.comment_contents
all = list(CommentLikeBridge.objects.all().values())
all_id = []
for obj in all:
all_id.append(obj['user_id'])
if request.user.id in all_id:
# for i in all:
# id = i['comment_id']
try:
CommentLikeBridge.objects.get(comment_id=comment_id)
comment_like = CommentLikeBridge.objects.get(comment_id=comment_id)
if comment_like.user_id == request.user.id:
comment_like.delete()
return Response({'message': f'{request.user}๋๊ป์ {contents[0:10]}...๋๊ธ์ ๊ณต๊ฐ์ ์ทจ์ํ์
จ์ต๋๋ค.'})
except:
comment_like = CommentLikeBridge(
comment_id = comment_id,
user_id = request.user.id,
like_id = like.id,
category = request.data.get('category')
)
comment_like.save()
return Response({'message': f'{request.user}๋๊ป์ {contents[0:10]}...๋๊ธ์ {comment_like.category}ํ์
จ์ต๋๋ค.'})
else:
comment_like = CommentLikeBridge(
comment_id = comment_id,
user_id = request.user.id,
like_id = like.id,
category = request.data.get('category')
)
comment_like.save()
return Response({'message': f'{request.user}๋๊ป์ {contents[0:10]}...๋๊ธ์ {comment_like.category}ํ์
จ์ต๋๋ค.'})
# ๊ณต๊ฐ์ ๊ฒ์๊ธ ํ3 ๋ฆฌ์คํ
class MostLikedArticleView(APIView):
def get(self, request):
articles = list(ArticleModel.objects.all().values())
articles_id = []
for article in articles:
articles_id.append(article['id'])
like_counts = []
for id in articles_id:
like_count = ArticleLikeBridge.objects.filter(article_id=id).count()
like_counts.append(like_count)
count_list = { name:value for name, value in zip(articles_id, like_counts)}
like_rank = sorted(count_list.items(), key=lambda x: x[1], reverse=True)[:3]
first = like_rank[0][0]
second = like_rank[1][0]
third = like_rank[2][0]
ranking = [first, second, third]
article_rank = ArticleModel.objects.filter(id__in = ranking)
return Response(ArticleSerializer(article_rank, many=True).data)
# ๊ณต๊ฐ์ ๋๊ธ ํ3 ๋ฆฌ์คํ
class MostLikedCommentView(APIView):
def get(self, request):
comments = list(CommentModel.objects.all().values())
comments_id = []
for comment in comments:
comments_id.append(comment['id'])
like_counts = []
for id in comments_id:
like_count = CommentLikeBridge.objects.filter(comment_id=id).count()
like_counts.append(like_count)
count_list = { name:value for name, value in zip(comments_id, like_counts)}
like_rank = sorted(count_list.items(), key=lambda x: x[1], reverse=True)[:3]
first = like_rank[0][0]
second = like_rank[1][0]
third = like_rank[2][0]
forth = like_rank[3][0]
fifth = like_rank[4][0]
sixth = like_rank[5][0]
ranking = [first, second, third, forth, fifth, sixth]
comment_rank = CommentModel.objects.filter(id__in = ranking)
return Response(CommentSerializer(comment_rank, many=True).data)
# ํฌํ์ ํ3 ๋ฆฌ์คํ
class MostVotedArticleView(APIView):
def get(self, request):
articles = list(ArticleModel.objects.all().values())
articles_id = []
for article in articles:
articles_id.append(article['id'])
vote_counts = []
for id in articles_id:
vote_count = ArticleVoteBridge.objects.filter(article_id=id).count()
vote_counts.append(vote_count)
count_list = { name:value for name, value in zip(articles_id, vote_counts)}
vote_rank = sorted(count_list.items(), key=lambda x: x[1], reverse=True)[:3]
first = vote_rank[0][0]
second = vote_rank[1][0]
third = vote_rank[2][0]
ranking = [first, second, third]
article_rank = ArticleModel.objects.filter(id__in = ranking)
return Response(ArticleSerializer(article_rank, many=True).data)
class SearchResult(APIView):
permission_classes = [permissions.AllowAny]
# ๊ฒ์ ๊ฒฐ๊ณผ ๋ฆฌ์คํ
def post(self, request):
keywords = request.data.get('search')
type= request.data.get('type')
# ๋ด์ฉ ๊ฒ์
if type == '๋ด์ฉ':
searched_contents = ArticleModel.objects.filter(article_contents__contains=keywords)
result = ArticleSerializer(searched_contents, many=True).data
return Response(result)
# ์์ฑ์ ๊ฒ์
elif type == '์์ฑ์':
searched_authors = ArticleModel.objects.filter(article_author__username=keywords)
result = ArticleSerializer(searched_authors, many=True).data
return Response(result)
# ์ ๋ชฉ + ๋ด์ฉ ๊ฒ์
elif type == '์ ๋ชฉ+๋ด์ฉ':
searched_contents = ArticleModel.objects.filter(article_contents__contains=keywords)
searched_titles = ArticleModel.objects.filter(article_title__contains=keywords)
searched = searched_contents.union(searched_titles)
result = ArticleSerializer(searched, many=True).data
return Response(result)
# ์ ๋ชฉ ๊ฒ์
else:
searched_titles = ArticleModel.objects.filter(article_title__contains=keywords)
result = ArticleSerializer(searched_titles, many=True).data
return Response(result)
# ๊ฒ์ํ๋ณ ์ํฐํด ๋ฆฌ์คํ
class ArticleByBoard(APIView):
def get(self, request):
boards = request.query_params.getlist('boards', '')
results = []
for board in boards:
articles = ArticleModel.objects.filter(board=board).order_by("-id")[:5]
result = ArticleSerializer(articles, many=True).data
results_data = {
f"{board}" : result
}
results.append(results_data)
return Response(results)