๐Ÿ‘ฆ ๋‚ด์ผ๋ฐฐ์›€์บ ํ”„/TIL(Today I Learned)

TIL_220617_DRF ๊ฐ•์˜

  • -

DRF ์˜ ๊ฝƒ Serializer ์— ๋Œ€ํ•ด์„œ ๋ฐฐ์šฐ๊ณ ,

 

Serializer ๋กœ ๊ณผ์ œ๋ฅผ ๋ฐ›์•˜๋‹ค.

 

์–ด๋А์ •๋„ ์ดํ•ด๋ฅผ ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ,

 

์ƒ๊ฐ๋ณด๋‹ค ์ƒ์†๊ณผ ๋‹ค๋ฅธ Serializer ์ถ”๊ฐ€ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„์ด ์žˆ์–ด

 

๋๋‚ด ๊ณผ์ œ๋ฅผ ์™„์„ฑํ•  ์ˆ˜ ์—†์—ˆ๋‹ค..

 

๊ทธ๋ž˜๋„ ํ•ด์„ค ๊ฐ•์˜๋ฅผ ํ†ตํ•ด ๋งˆ์ง€๋ง‰๊นŒ์ง€ ์ฐ๋จนํ•ด๋ณด์•˜๋‹ค.

 


์‚ฌ์‹ค ์—๋Ÿฌ๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ๋‚ด๊ฐ€ ์‹ค์ˆ˜ํ•œ ๋‚ด์šฉ์ด์ง€๋งŒ, ๋‘ ๋ฒˆ ์‹ค์ˆ˜ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ์ ์–ด๋‘”๋‹ค.

 

<๊ด€๋ฆฌ์ž ๊ณ„์ • ์—๋Ÿฌ>
์›์ธ : 
1) ํƒ€์ž„์–ดํƒ ์‹œ ์™„์ „ ์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•˜๊ณ  ์‹œ์ž‘.
2) ํƒ€์ž„์–ดํƒ 2๋ฒˆ ๋ฌธ์ œ์—์„œ USERNAME_FIELD ๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๊ณ„์† ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ๊ธฐ์ดํ•œ ํ˜„์ƒ
3) ์—๋Ÿฌ ์ฝ”๋“œ๋„ ๋œจ์ง€ ์•Š๊ณ  ๊ณ„์† ์‚ฌ์šฉ์ž ์ด๋ฆ„๋ถ€ํ„ฐ ์ž‘์„ฑํ•˜๋ผ๊ณ  ํ•จ.

ํ•ด๊ฒฐ : AUTH_USER_MODEL = 'user.User'
๊ณ„์ • ๋ชจ๋ธ์„ ์ž์‹ ์ด ์ปค์Šคํ…€ํ•œ ๊ณ„์ • ๋ชจ๋ธ๋กœ ๋ฉ”์ธ์œผ๋กœ ์ง€์ •์„ ๊ผญ ํ•ด์ค˜์•ผ ์žฅ๊ณ ์˜ ๊ธฐ๋ณธ ๋ชจ๋ธ์—์„œ ์ž์‹ ์ด ์ปค์Šคํ…€ํ•œ ๋ชจ๋ธ๋กœ ์ ์šฉ๋˜์–ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
(๊ธฐ๋ณธ์ ์ธ๊ฑด๋ฐ.. ๊ด€๋ฆฌ์ž ๋ชจ๋ธ ์ง€์ •์„ ์•ˆํ•ด์ค€ ์‹ค์ˆ˜.. ใ… )

 

<input ์ด ์ •์ƒ์ ์œผ๋กœ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ>

# ๊ธ€ ์ƒ์„ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„ def post(self, request): user = request.user title = request.data.get("title", "") contents = request.data.get(<<"contents">>, "") category = request.data.get("category", []) ==================================================================== <<< input >>> { "title" : "์•ˆ๋…•ํ•˜์„ธ์š” ๋ฐ˜๊ฐ‘์Šต๋‹ˆ๋‹ค.", <<"contents">> : "๊ธ€ ๋‚ด์šฉ ์ž…๋‹ˆ๋‹ค. ์™€์šฐ ๋นก๋นก์ด ์•„์ฃ ์”จ์•ผ!!! ํ˜ธ์šฐ!!!!!!", "category" : [4, 5] }


๋ฆฌํ€˜์ŠคํŠธ๋กœ ๋ฐ›์•„์˜ค๋Š” ํ•„๋“œ๋ช…์€ ๊ผญ ์ž…๋ ฅ๋ฐ์ดํ„ฐ ๋ช…๊ณผ ๊ฐ™์•„์•ผํ•œ๋‹ค.

 


์ฐธ๊ณ ๊ฐ€ ๋˜์—ˆ๋˜ ์ž๋ฃŒ๋“ค์„ ์ฐพ์•„๋ดค๋‹ค.

 

Serializer ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์ถœ์ฒ˜ ์œ ํˆฌ๋ธŒ : https://www.youtube.com/watch?v=V4NjlXiu5WI 

 


class Comment(models.Model): # Article ์— ์ž‘์„ฑํ•œ ์ฝ”๋ฉ˜ํŠธ์˜ ์ถœ์ฒ˜(์ž‘์„ฑ์ž) / CASCADE ๋Œ“๊ธ€์˜ ์ž‘์„ฑ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ•จ๊ป˜ ๋Œ“๊ธ€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์„ค์ • user = models.ForeignKey('user.User', verbose_name="๋Œ“๊ธ€ ์ž‘์„ฑ์ž", on_delete=models.CASCADE) # Article ๊ณผ์˜ ๋Œ“๊ธ€ ๊ด€๊ณ„ ์ •์˜ / CASCADE ๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ•จ๊ป˜ ๋Œ“๊ธ€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์„ค์ • article = models.ForeignKey(Article, verbose_name="๋Œ“๊ธ€์„ ์ž‘์„ฑํ•œ ๊ธ€", on_delete=models.CASCADE) content = models.TextField("๋Œ“๊ธ€ ๋‚ด์šฉ") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return f"{self.user.username} ๋‹˜์ด ์ž‘์„ฑํ•˜์‹  ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค."
# Article ์— ์ž‘์„ฑํ•œ ์ฝ”๋ฉ˜ํŠธ์˜ ์ถœ์ฒ˜(์ž‘์„ฑ์ž) / CASCADE ๋Œ“๊ธ€์˜ ์ž‘์„ฑ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ•จ๊ป˜ ๋Œ“๊ธ€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์„ค์ • user = models.ForeignKey('user.User', verbose_name="๋Œ“๊ธ€ ์ž‘์„ฑ์ž", on_delete=models.CASCADE) # Article ๊ณผ์˜ ๋Œ“๊ธ€ ๊ด€๊ณ„ ์ •์˜ / CASCADE ๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํ•จ๊ป˜ ๋Œ“๊ธ€ ๋ฐ์ดํ„ฐ ์‚ญ์ œ ์„ค์ • article = models.ForeignKey(Article, verbose_name="๋Œ“๊ธ€์„ ์ž‘์„ฑํ•œ ๊ธ€", on_delete=models.CASCADE)
from django.contrib import admin from blog.models import Comment # Register your models here. admin.site.register(Comment)
class HobbySerializer(serializers.ModelSerializer): # ์ด ๊ธฐ๋Šฅ์„ ํ†ตํ•ด ์ž์‹ ์˜ ์ทจ๋ฏธ์™€ ํ•ด๋‹นํ•˜๋Š” ์œ ์ € ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ์Œ. # ์ž์‹ ์ด ์›ํ•˜๋Š” ๋ฉ”์„œ๋“œ ํ•„๋“œ ์ƒ์„ฑ ๊ฐ€๋Šฅ same_hobby_users = serializers.SerializerMethodField() # SerializerMethodField() ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” get_same_hobby_users ๊ผญ ํ•„์š” def get_same_hobby_users(self, obj): # obj : hobby model ์˜ obj user_list = [] for user_profile in obj.userprofile_set.all(): user_list.append(user_profile.user.username) # return [up.user.username for up in obj.userprofile_set.all()] ์ถ•์•ฝ์‹ return user_list class Meta: model = Hobby fields = ['name', 'same_hobby_users'] class UserProfileSerializer(serializers.ModelSerializer): hobby = HobbySerializer(many=True) # input data queryset ์ผ ๊ฒฝ์šฐ class Meta: model = UserProfile # ๋ถˆ๋Ÿฌ์˜ค๊ณ ์ž ํ•˜๋Š” user ์˜ ๊ธฐ๋ณธ ์ •๋ณด์™€ ์ƒ์„ธ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ fields = ['introduction', 'birthday', 'age', 'hobby'] # __all__ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ถˆํ•„์š”ํ•œ ์ •๋ณด๋„ ํ•จ๊ป˜ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— # ํŠน์ • ์ •๋ณด์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๋งŒ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ง์ ‘ ์„ค์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. class UserSerializer(serializers.ModelSerializer): # object userprofile = UserProfileSerializer() class Meta: model = User # ์—ญ์ฐธ์กฐ๋กœ userprofile ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ fields = ["username", "password", "fullname", "email", "join_date", "userprofile"]
class UserSerializer(serializers.ModelSerializer): # object userprofile = UserProfileSerializer() # ํ•ด๋‹น ์œ ์ €์˜ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ userarticle = ArticleSerializer(source="article_set" ,many=True) class Meta: model = User # ์—ญ์ฐธ์กฐ๋กœ userprofile ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ fields = ["username", "password", "fullname", "email", "join_date", "userprofile", "userarticle"]

 - ๋งŒ์•ฝ title์ด 5์ž ์ดํ•˜๋ผ๋ฉด ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋ฆฌํ„ดํ•ด์ฃผ์„ธ์š”
 - ๋งŒ์•ฝ contents๊ฐ€ 20์ž ์ดํ•˜๋ผ๋ฉด ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋ฆฌํ„ดํ•ด์ฃผ์„ธ์š”
 - ๋งŒ์•ฝ ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋ฆฌํ„ดํ•ด์ฃผ์„ธ์š”

# ๊ธ€ ์ƒ์„ฑ ๊ธฐ๋Šฅ ๊ตฌํ˜„ def post(self, request): user = request.user title = request.data.get("title", "") contents = request.data.get("contents", "") category = request.data.get("category", []) # ๊ธ€์ž์ˆ˜ ์กฐ๊ฑด ์ดํ•˜์ผ ๊ฒฝ์šฐ if len(title) <= 5: return Response({"error" : "ํƒ€์ดํ‹€์€ 5์ž ์ด์ƒ ์ž‘์„ฑํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค."}, status=status.HTTP_400_BAD_REQUEST) # ๊ธ€์ž์ˆ˜ ์กฐ๊ฑด ์ดํ•˜์ผ ๊ฒฝ์šฐ if len(contents) <= 20: return Response({"error" : "๊ธ€ ๋‚ด์šฉ์€ 20์ž ์ด์ƒ ์ž‘์„ฑํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค."}, status=status.HTTP_400_BAD_REQUEST) if not category: return Response({"error" : "์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์ง€์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."}, status=status.HTTP_400_BAD_REQUEST) article = ArticleModel( user = user, title = title, content = contents ) article.save() article.category.add(*category) return Response({"message": "์„ฑ๊ณต!"}, status=status.HTTP_200_OK)

 - ํ…Œ์ŠคํŠธ ํ•  ๋•Œ์—๋Š” ๊ฐ€์ž… ํ›„ 3๋ถ„ ์ด์ƒ ์ง€๋‚œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒŒ์‹œ๊ธ€์„ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์„ธ์š”
 - join_date๋Š” datetime field๋กœ ๋งŒ๋“ค์–ด์ฃผ์„ธ์š”

from rest_framework.permissions import BasePermission from datetime import timedelta from django.utils import timezone class RegisterdMoreThanThreeDaysUser(BasePermission): ''' ๊ฐ€์ž…์ผ ๊ธฐ์ค€ 3์ผ ์ด์ƒ ์ง€๋‚œ ์‚ฌ์šฉ์ž๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅ ''' message = '๊ฐ€์ž… ํ›„ 3์ผ ์ด์ƒ ์ง€๋‚œ ์‚ฌ์šฉ์ž๋งŒ ์‚ฌ์šฉํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.' def has_permission(self, request, view): user = request.user # ํ•จ์ถ•์‹ ์กฐ๊ฑด 1) ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž์ธ๊ฐ€ ์กฐ๊ฑด 2) ๊ฐ€์ž…์ผ ๊ธฐ์ค€ 3์ผ์ด ์ง€๋‚ฌ๋Š”๊ฐ€ return bool(user.is_authenticated and request.user.join_date < (timezone.now() - timedelta(days=3))) ==================================================================== class ArticleView(APIView): permission_classes = [RegisterdMoreThanThreeDaysUser] # ์ปค์Šคํ…€ permissions



 
Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.