아래 사례는 Udemy의 "The complete Guide to Django Restframework and Vue JS" 강의 중 Section3의 : Django REST Framework - Level One의 내용을 요약정리한 것입니다.
장고 DRF 실습을 위해 가상환경을 만들고, 아래 프로그램들을 사전에 설치합니다.
pip install requests
pip install django
pip install pillow
pip install djangorestframework
pip list # 설치된 프로그램 확인
class Article(models.Model):
#author = models.ForeignKey(Journalist, on_delete=models.CASCADE, related_name="articles")
author = models.CharField(max_length=120)
title = models.CharField(max_length=120)
description = models.CharField(max_length=200)
body = models.TextField()
location = models.CharField(max_length=120)
publication_date = models.DateTimeField()
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return f"{ self.author } { self.title }"
python manage.py createsuperuser
from news.models import Article # 사용할 모델 임포트
admin.site.register(Article) # 어드민에 해당 모델 등록
from rest_framework import serializers
from news.models import Article
class ArticleSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
author = serializers.CharField()
title = serializers.CharField()
description = serializers.CharField()
body = serializers.CharField()
location = serializers.CharField()
publication_date = serializers.DateTimeField()
active = serializers.BooleanField()
created_at = serializers.DateTimeField(read_only=True)
updated_at = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
print(validated_data)
return Article.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.author = validated_data.get('author', instance.author)
instance.title = validated_data.get('title', instance.title)
instance.description = validated_data.get('description', instance.description)
instance.body = validated_data.get('body', instance.body)
instance.location = validated_data.get('location', instance.location)
instance.publication_date = validated_data.get('publication_data', instance.publication_date)
instance.active = validated_data.get('active', instance.active)
instance.save()
return instance
2-1) Model Instance -> Serialize하기
# 필요한 모듈 임포트
> from news.models import Article
> from news.api.serializers import ArticleSerializer
# Article 객체, serializer 각각 변수에 담기
> article_instance = Article.objects.first()
> serializer = ArticleSerializer(article_instance)
# Article 객체 데이터 접근하기
> article_instance
<Article: Jone doe How to be CEO>
> Article.objects.values()
<QuerySet [{'id': 2, 'author': 'Jone doe', 'title': 'How to be CEO', 'description': "it's tough", 'body': 'hahaha', 'location': 'Seoul', 'publication_date': datetime.datetime(2020, 7, 8, 9, 12, 41), 'active': True, 'created_at': datetime.datetime(2020, 7, 8, 9, 12, 43, 445883, tzinfo=<UTC>), 'updated_at': datetime.datetime(2020, 7, 8, 9, 12, 43, 445907, tzinfo=<UTC>)}]>
> article_instance.author
'Jone doe'
# serializer 데이터 접근하기 (Serializer는 파이썬 딕셔너리 타입)
> serializer.data
{‘id': 2, 'author': 'Jone doe', 'title': 'How to be CEO', 'description': "it's tough", 'body': 'hahaha', 'location': 'Seoul', 'publication_date': '2020-07-08T09:12:41Z', 'active': True, 'created_at': '2020-07-08T09:12:43.445883Z', 'updated_at': '2020-07-08T09:12:43.445907Z'}
> serializer.data['author']
’Jone doe'
# 타입 비교
> type(article_instance)
<class 'news.models.Article'>
> type(serializer.data)
<class 'rest_framework.utils.serializer_helpers.ReturnDict'>
2-2) Data를 Deserialize하기
> from rest_framework.renderers import JSONRenderer
# serializer.data를 JSON화
> json = JSONRenderer().render(serializer.data)
> json
b'{"id":2,"author":"Jone doe","title":"How to be CEO","description":"it\'s tough","body":"hahaha","location":"Seoul","publication_date":"2020-07-08T09:12:41Z","active":true,"created_at":"2020-07-08T09:12:43.445883Z","updated_at":"2020-07-08T09:12:43.445907Z"}'
# json를 파이썬 딕셔너리화
> import io
> from rest_framework.parsers import JSONParser
> stream = io.BytesIO(json)
> data = JSONParser().parse(stream)
> data
{'id': 2, 'author': 'Jone doe', 'title': 'How to be CEO', 'description': "it's tough", 'body': 'hahaha', 'location': 'Seoul', 'publication_date': '2020-07-08T09:12:41Z', 'active': True, 'created_at': '2020-07-08T09:12:43.445883Z', 'updated_at': '2020-07-08T09:12:43.445907Z'}
# 타입 비교
> type(json)
<class 'bytes'>
> type(stream)
<class '_io.BytesIO'>
> type(data)
<class 'dict'>
2-3) Serializer화 하여 데이터 저장하기
> serializer = ArticleSerializer(data=data)
> serializer.is_valid()
True
# serializer로 객체에 데이터 저장하기
> serializer.validated_data
OrderedDict([('author', 'Jone doe'), ('title', 'How to be CEO'), ('description', "it's tough"), ('body', 'hahaha'), ('location', 'Seoul'), ('publication_date', datetime.datetime(2020, 7, 8, 9, 12, 41, tzinfo=<UTC>)), ('active', True)])
> serializer.save()
{'author': 'Jone doe', 'title': 'How to be CEO', 'description': "it's tough", 'body': 'hahaha', 'location': 'Seoul', 'publication_date': datetime.datetime(2020, 7, 8, 9, 12, 41, tzinfo=<UTC>), 'active': True}
<Article: Jone doe How to be CEO>
# 데이터 저장되었는지 확인
> Article.objects.all()
<QuerySet [<Article: Jone doe How to be CEO>, <Article: Jone doe How to be CEO>]
serializer가 어떤 역할을 수행하는지 잘 익혀 두어야 잘 활용할 수 있다. 따라서 아래 과정에 대해 상세히 알아둘 필요가 있다.
serializer = CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}
serializer = CommentSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
comment = serializer.save()
# .save() will create a new instance.
serializer = CommentSerializer(data=data)
serializer.save()
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
serializer.save()
1) Passing additional attributes to .save()
saving instance할 때 추가 정보를 전달하고 싶을 때가 있다. 가령, 현재 시간이라거나 현재 사용자 정보 등의 경우 말이다. 이렇게 추가로 정보를 전달하고 싶을 때는 .save()할 때 추가 정보를 전달하면 된다.
serializer.save(owner=request.user)
2) Overrding .save() directly
Contact form 같은 경우, 객체를 생성할 필요가 없이 단지 이메일이나 혹은 메시지를 보내는 로직만 필요한 경우가 있다. 이 때는 .save()의 오버라이드해서 로직을 수정해 줄 필요가 있다.
class ContactForm(serializers.Serializer):
email = serializers.EmailField()
message = serializers.CharField()
def save(self):
email = self.validated_data['email']
message = self.validated_data['message']
send_email(from=email, message=message)
구체적인 필드 종류는 공식 문서를 참조할 것, 단 주로 사용하는 serializer의 핵심 속성들은 잘 이해하고 있어야 함.