0313 TIL

looggi·2023년 3월 13일
0

TILs

목록 보기
34/114
post-thumbnail

django

serializer

  1. DRF Serializer는 무엇이며, 어떤 기능을 수행합니까?

DB에 저장된 데이터를 직렬화하여 JSON형태로 바꾸기 쉬운 파이썬 데이터타입으로 변환해줍니다. JSON파일을 이용해 데이터를 주고받게 되면 시스템/언어에 구애받지 않고 사용이 가능하며 가볍다는 장점이 있습니다.
+serialize, deserialize, 데이터 검증하는 기능을 수행합니다

class BaseSerializer(Field):
    def __init__(self, instance=None, data=empty, **kwargs):
        # 생략
        
class Serializer(BaseSeializer):

첫번째 인자가 인스턴스이므로 데이터를 전달할 때는 data=이 꼭 필요하다

serializer = PostSerializer(reqeust.data) # 오류
# 인스턴스는 첫번째 인자이므로 전달할 때 키워드가 필요없다
serializer = PostSerializer(post)
serializer = PostSerializer(data=request.data)
# 첫번째 인자가 있으면 두번째가 구분이 되어 키워드가 필요없다
serializer = PostSerializer(post, data=reqeust.data)
serializer = PostSerializer(post, reqeust.data)

serializers.ModelSerializer를 상속받으면 아래처럼 시리얼라이저에서 필드 정의하는 과정이 불필요함

# serializers.py 
from rest_framework import serializers
 
class SnippetSerializer():
    id = IntegerField(label='ID', read_only=True)
    title = CharField(allow_blank=True, max_length=100, required=False)
    style = ChoiceField(choices=[('autumn', 'autumn'), ('borland', 'borland'), ('bw', 'bw'), ('colorful', 'colorful')...
# 또는
# class SnippetSerializer(serializers.Serializer):
#    title = serializers.CharField()
#    content = serializers.TextField()

사용

# views.py
from snippets.serializers import SnippetSerializer
serializer = SnippetSerializer()
print(repr(serializer))  

  1. JSON 형식으로 데이터를 받고, Serializer를 통해서 JSON형식으로 데이터를 반환하는 이유는 무엇인가요?

데이터 통신을 위해서는 데이터가 바이트 타입으로 변환되어야하는데 시리얼라이즈를 통해 바이트 타입으로 변환된 데이터는 JSON으로 쉽게 변환할 수 있으며 디시리얼라이즈도 마찬가지이다.
또한 XML보다 가볍고 특정 언어에 종속되지 않아서 타 어플리케이션과 데이터를 주고받기가 좋다는 장점이 있다. 딕셔너리 형태의 구조와 단순한 문자열로 이루어져있다는 점 또한 시스템 및 인간 모두가 이해하기 좋다는 장점이 된다.

JSON->JSONDataHandler->byte[]


  1. Serializer를 통해서 특정 모델에 존재하지 않지만, 관계 있는 테이블의 필드 레코드를 반환하는 방법에 대해서 설명하시오

ForiegnKey의 관계에 있는 모델의 필드를 사용할 때는 해당 필드를 사용하고자 하는 시리얼라이저 클래스 안에서 SerializerMethodField를 통해 가져오고 get_해당 필드명(self,object) 함수를 시리얼라이저 클래스 안에 정의해서 필드에 해당하는 객체를 리턴해주고 Meta 클래스의 fields=에 추가해줍니다. 이때 시리얼라이저 안에서의 필드명과 가져오는 함수의 메소드명은 원하는대로 설정이 가능합니다.


  1. Serializer를 통해서 역참조 하는 방법에 대해서 설명하시오

foreignkey필드에 명시된 related_name이 없다면 기본적으로 모델_set을 시리얼라이져 메타 클래스의 fields에 명시해주면 사용할 수 있습니다.

Serializer relations

# models.py
class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    duration = models.IntegerField()

    class Meta:
        unique_together = ['album', 'order']
        ordering = ['order']

    def __str__(self):
        return '%d: %s' % (self.order, self.title)

Track 이 Album을 정참조 -> Album을 Track 이 역참조

모델 간의 관계에서 다(多)에 해당하는 필드라면 many=True 옵션을 넣어줘야한다

🧦references to another entity

정참조

tracks가 표현되는 형태에 따라서 종류가 나뉨

  • StringRelatedField
class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.StringRelatedField(many=True) # read only.
  • PrimaryKeyRelatedField
    tracks의 pk가 nested되어 들어감
  • HyperlinkedRelatedField
    tracks의 hyperlink가 nested되어 들어감
  • SlugRelatedField
    slug_field=에 명시된 track의 필드에 해당되는 값으로 tracks에 nested되어 표현됨
tracks = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='title'
     )

🧦 Nested relationships

referred entity be embedded/nested in the representation of the objects that refers to it

🧦 Reverse relations

역참조 관계는 모델 필드에 정의한 related_name이나 따로 정의한 related_name이 없다면 모델_set를 시리얼라이저 클래스 내부에 있는 Meta 클래스 fields=에 써준다

class AlbumSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ['track_set', ...]

https://www.django-rest-framework.org/api-guide/relations/


  1. Serializer에서 어떻게 객체를 validate하게 됩니까?

validate() 함수를 통해 다수의 필드에 대해 검사합니다 - 검사 내용을 한번에 작성할 수 있음

  • 객체를 validate하는 방법
class PostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)

    def validate(self, data):
        if '제목' not in data['title']:
            raise ValidationError('제목이라는 말이 들어가야 합니다.')
        return data
  • 필드를 validate하는 방법
# serializers.py

from rest_framework import serializers
from rest_framework.exceptions import ValidationError

class PostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)

    def validate_title(self, value):
        if '제목' not in value:
            raise ValidationError('제목이라는 말이 들어가야 합니다.')
        return value

  1. Serializer에서 Custom Validation을 하는 이유는 무엇입니까?

built-in validator들이 모든 케이스를 커버하지 못하기 때문에 필요한 상황에 맞춰 custom validator를 짜야한다.


  1. Serailizer Custom validate함수를 통해 오류 케이스를 어떻게 처리합니까?

조건문으로 오류 케이스를 작성한 후 raise ValidationError() 내부에 오류 메세지를 작성합니다


  1. Serializer에서 create, update 함수는 어떤 기능을 수행합니까?
    create는 validated_data를 받아서 새로운 DB인스턴스를 생성하고 update는 기존의 인스턴스를 수정합니다

is_valid()로 검증된 validated_data를 받아서 .save() 호출시 인스턴스가 있으면 update()를 통해 저장하고 없으면 create를 통해 인스턴스 생성 후 저장

https://seoyoung2.github.io/django/2020/08/16/Serializer.html

빽준 문제 풀기

➡️ 1,2,3 더하기

import sys

T=int(input())

for t in range(T):
    n=int(sys.stdin.readline())
    dp = [0]*(n+1) # 0부터 계산하므로 n개까지 하면 list index out of range
    for i in range(1,len(dp)):
        dp[i]=dp[i-3]+dp[i-2]+dp[i-1]
        if i<4: # 1-3까지
            print(i)
            dp[i]+=1 # 자기 자신만으로도 완성하는 경우가 추가됨
    print(dp[n])
print(dp) # n=5일 때 [0, 1, 2, 4, 7, 13]

DP는 경우의 수를 어느정도 계산해보고 패턴을 찾아야하는 것 같다
반복되는 부분이 전체를 만들 때 DP로 문제를 푼다는데 for문이나 재귀를 통해서 구현할 수 있다는데 일단 for문을 이용해서 구현하는 방법

n+1까지 만들어야 n개까지 모두 저장할 수 있어서 초기 dp리스트는 n+1 크기로 만들어야하고 1-3까지는 자기 숫자로도 만들 수 있어서 +1을 해줘야한다

profile
looooggi

0개의 댓글