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
4μΌμ°¨ κ³Όμ
1. blog μ±μ <κ²μκΈ, μ¬μ©μ, λ΄μ©>μ΄ ν¬ν¨λ comment ν μ΄λΈμ μμ±ν΄μ£ΌμΈμ
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} λμ΄ μμ±νμ λκΈμ
λλ€."
2. μΈλ ν€λ₯Ό μ¬μ©ν΄μ Article, User ν
μ΄λΈκ³Ό κ΄κ³λ₯Ό λ§Ίμ΄μ£ΌμΈμ
# 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)
3. admin.pyμ commentλ₯Ό μΆκ°ν΄ μμ λ‘κ² μμ±, μμ ν μ μλλ‘ ν΄μ£ΌμΈμ
from django.contrib import admin
from blog.models import Comment
# Register your models here.
admin.site.register(Comment)
4. serializerλ₯Ό νμ©ν΄ λ‘κ·ΈμΈ ν μ¬μ©μμ κΈ°λ³Έ μ 보μ μμΈ μ 보λ₯Ό 리ν΄ν΄ μ£Όλ κΈ°λ₯μ λ§λ€μ΄μ£ΌμΈμ
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"]
5. 4λ²μ serializerμ μΆκ°λ‘ λ‘κ·ΈμΈ ν μ¬μ©μμ κ²μκΈ, λκΈμ 리ν΄ν΄μ£Όλ κΈ°λ₯μ ꡬνν΄μ£ΌμΈμ
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"]
6. blog μ±μ title / category / contentsλ₯Ό μ
λ ₯λ°μμ κ²μκΈμ μμ±νλ κΈ°λ₯μ ꡬνν΄μ£ΌμΈμ
- λ§μ½ 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)
7. custom permission classλ₯Ό νμ©ν΄ κ°μ
ν 3μΌ μ΄μ μ§λ μ¬μ©μλ§ κ²μκΈμ μΈ μ μλλ‘ ν΄μ£ΌμΈμ
- ν
μ€νΈ ν λμλ κ°μ
ν 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