티스토리 뷰

반응형

상황은 다음과 같다. django rest framework를 사용중이고, serializer를 통해 직렬화를 진행했다. 그리고 return을 하려는데 잘 안된다. 관련 내용을 정리해 보겠다. 회원가입, 로그인, jwt관련 인증은 아래의 url을 따라가서 확인하자.

 

 

기본 설정

> 모델설정은 아래와 같이했다. BaseUserManager와 AbstractBaseUser를 사용한 것은 로그인과 회원가입을 위해 장고 내부기능을 활용한것이다. 자세한 부분은 여기를 눌러보자. 여기서 중요한 것은 나는 User이름을 MyUser로 했다는 것이다. 나같은 경우는 사용자 인증으로 User 모델을 했지만, 다른 models.py의 class 들도 적용가능하다.

 

# models.py
from django.db import models

# Create your models here.
from django.db import models
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)


class MyUserManager(BaseUserManager):
    def create_user(self, email, phone_number, address, password=None):
        """
        Creates and saves a User with the given email, date of
        birth and password.
        """
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
            phone_number = phone_number, 
            address = address,
            # date_of_birth=date_of_birth,
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, phone_number, address, password=None):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(
            email,
            password=password,
            # date_of_birth=date_of_birth,
            phone_number = phone_number,
            address = address
        )
        user.is_admin = True
        user.save(using=self._db)
        return user


class MyUser(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    phone_number = models.CharField(blank=True, max_length=50)
    address = models.CharField(blank=True, max_length=300)
    items_of_interest = models.CharField(blank=True, max_length=300)
    job = models.CharField(blank=True, max_length=50)
    # date_of_birth = models.DateField()
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    objects = MyUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['phone_number, address']

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin

 

 

 

case 1

> 기본적인 회원 조회를 return하기

 

# views.py
from django.core import serializers
from .models import MyUser

def user_list(request):
    queryset = MyUser.objects.all()
    data = serializers.serialize("json", queryset) 
    return HttpResponse(content=data)

 

MyUser의 내용인 회원들을 전부 쿼리셋으로 불러온다.쿼리셋을 JSON으로 바로 변환은 불가능하다. serializers를 활용해 json으로 바꿔야한다. 전체 컬럼이 json으로 바뀌는 것을 알 수 있다.  이 방법은 간단하지만, validation이 안된다. 그리고 특정 columns만 넣고 싶다면 추가적으로 serializers.py를 추가해 줘야한다. 매우 간단하지만... 단점은 원하지 않는 columns도 가져와서 JSON이 복잡해지는 것과 한글이 변환되어 넘어가서 추가 작업이 필요하다.

 

 

 

 

 

case 2

models.py에 등록한 MyUser의 데이터중 특정 컬럼들만 뽑가아서 가져와 보자.

 

 

serializers.py 관련 내용은 아래와 같다.

from rest_framework import serializers

# 방법1
class BaseSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    phone_number = serializers.CharField()
    address = serializers.CharField()

# 방법2
class UserSerializer(serializers.BaseSerializer):
    def to_representation(self, instance):
        return {
            'email': instance.email,
            'phone_number': instance.phone_number,
            'address': instance.address
        }

 

위의 방법1과 2는 같은 결과를 도출해 낸다. 내가 가진 MyUser의 columns 중에 email, phone_number, address만 뽑아서 가지고 올 수 있도록 설정을 했다. 공식문서에 따르면 기본적인 조회는 BaseSerializer를 활용하고 to_representation을 사용하면 된다고 나와있다. 그리고 views.py 설정을 하자.

 

from rest_framework.response import Response
from .serializers import BaseSerializer, UserSerializer
from rest_framework.decorators import authentication_classes, permission_classes

# 방법1
@api_view(['GET'])
@authentication_classes([])
@permission_classes([])
def user_list(request):
    queryset = MyUser.objects.all()
    serialized_data = UserSerializer(queryset, many=True) 
    return Response(data=serialized_data.data)
    
# 방법2
@api_view(['GET'])
@authentication_classes([])
@permission_classes([])
def user_list(request):
    queryset = MyUser.objects.all()
    serialized_data = BaseSerializer(queryset, many=True) 
    return Response(data=serialized_data.data)
    

 

내용을 확인해 보면 serializers.py에서 가져오는 클래스에 따라 다른것을 알 수 있다.

 

위의 serialized_data 변수를 보면 many=True가 적혀있다. 그 이유는 쿼리셋이 하나가 아니라 리스트 안에 여러개의 딕셔너리가 들어가기 때문에 넣어주는 것이다. many=True를 안 넣으면, 오류가 발생한다. 만약, objects.all()이 아닌 하나만 부른다면 넣어주지 않아도 상관없다.

 

@authentication_classes([])@permission_classes([])는 만약 응답 내용이 아래와 같은 인증 error가 발생한다면, 추가해서 넣어주자.

 

{
    "detail": "Authentication credentials were not provided."
}

 

 

위의 2가지 방법중에 마음에 드는 방법을 사용하면 된다.

 

 

 

 

case3

> ModelSerializer를 상속 받은 후에 Meta 클래스를 통해서 작성할 수도 있다. 방법은 위랑 거의 비슷하다.

 

#serializers.py
from rest_framework import serializers
from .models import MyUser

class MetaUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyUser
        fields = (
            "email",
            "phone_number",
            "address"
        )

 

model에 내가 설정한 models.py내용을 넣어주고 fields에 내가 사용할 fields를 넣어준다.

 

 

# views.py
from .serializers import MetaUserSerializer
from rest_framework.decorators import authentication_classes, permission_classes
@api_view(['GET'])
@authentication_classes([])
@permission_classes([])
def user_list(request):
    queryset = MyUser.objects.all()
    serialized_data = MetaUserSerializer(queryset, many=True) 
    return Response(data=serialized_data.data)

 

views.py에서 serializer 내용을 가져와서 위와같이 적어주면된다.

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함