개발자 블로그

[django] 오늘의 공부 정리 0613 본문

Django/오늘의 공부

[django] 오늘의 공부 정리 0613

hayongwoon 2022. 6. 13. 22:23

1. postman 활용

1-1. postman에서 csrf 토큰 넣어주기. 

 

1-2. postman을 활용한 유저 로그인

json은 '' 이 안되고 쌍 따움표로 "" 안에 키(필드 네임) 벨류(아이디 또는 비밀번호 값) 값 설정

 

2. serializes.ModelSerializer

  • meta class 를 통해 필드를 지정하고 커스텀할 수 있음.
  • password는 리턴할 때 writeonly 로 반환 반환을 아예 안하면 안되는가? 비밀번호인데? 이 부부은 추후 사용자가 정보를 수정하거나 업데이트 해야할 때, 필요하기 때문 그래서 반환을 하되 extra_kwargs로 read는 제외한 writeonly를 설정 
  • many = True 설정하면 쿼리셋, 기본은 False로 객체만 반환
  • 순환참조에러 -> Import

user.serializer
blog.serializer
순환참조 에러

해당 에러는 참조한 객체가 서로 순환되어 import가 원처럼 도는 것을 의미한다. 위 시리얼라이저를 선언한 것을 보면 Article -> User -> UserProfile로 엮이는 것을 볼 수 있다. 때문에 게시글 정보와 작성자 정보를 가져오고 싶다면, import를 해서 참조하는 것이 아닌, blog에 유저에 대한 시리얼라이즈를 따로 만들어줘야한다.

solution
return in postman

  • 하용운이라는 유저의 정보를 가져오고 싶다. 유저의 프로필과 취미까지 나아가 나와 같은 취미를 갖고있는 사람들의 이름까지도(역참조)
class UserApiView(APIView):
    # 로그인
    def post(self, request):
        username = request.data.get('username', '')
        password = request.data.get('password', '')

        user = authenticate(request, username=username, password=password)
        if not user:
            return Response({"error": "존재하지 않는 계정이거나 패스워드가 일치하지 않습니다."}, status=status.HTTP_401_UNAUTHORIZED)

        login(request, user)
        return Response({"message": "로그인 성공!!"}, status=status.HTTP_200_OK)

    # 로그인 한 유저의 모든 정보
    def get(self, request):
        user = request.user
        # serializer에 queryset을 인자로 줄 경우 many=True 옵션을 사용해야 한다.
        serialized_user_data = UserSerializer(user).data
        return Response(serialized_user_data, status=status.HTTP_200_OK)

시리얼라이즈를 통해 유저의 정보를 얼마나 자세히 참조해서 가져올지 알아보자!

from rest_framework import serializers
from blog.serializers import ArticleSerializer

from user.models import User as UserModel
from user.models import UserProfile as UserProfileModel
from user.models import Hobby as HobbyModel
from blog.models import Article as ArticleModel

class HobbySerializer(serializers.ModelSerializer):
    people_with_my_hobby = serializers.SerializerMethodField()
    #get_변수이름 으로 함수 선언하면 해당 함수의 리턴값이 해당 변수를 참조하게 되고 필드로 설정할 수 있음. 
    # 역참조를 불러오기 위해선 해당 객체를 받아와서 각 객체마다의 정보를 가져와야한다. 때문에 함수를 선언하여 리턴값을 불러와 필드로 지정할 수 있는 serializers.SerializerMethodField() 활용
    def get_people_with_my_hobby(self, obj): 
        #취미 객체로 부터 자신을 참조하고있는 모든 프로필을 가져오고 그 프로필의 유저네임을 가져온다.
        #나를 제외하고 가져올 수는 없을까...? exclude(user=user)를 사용하려면 hobby의 객체들의 근원지인 user를 가져와야하는데....
        return [user_profile.user.fullname for user_profile in obj.userprofile_set.all()]

    class Meta:
        # serializer에 사용될 model, field지정
        model = HobbyModel
        # 모든 필드를 사용하고 싶을 경우 fields = "__all__"로 사용
        fields = ["name", "people_with_my_hobby"]

class UserProfileSerializer(serializers.ModelSerializer):
    hobby = HobbySerializer(many=True)

    class Meta:
        # serializer에 사용될 model, field지정
        model = UserProfileModel
        # 모든 필드를 사용하고 싶을 경우 fields = "__all__"로 사용
        fields = "__all__"

class UserSerializer(serializers.ModelSerializer):
    userprofile = UserProfileSerializer()

    class Meta:
        # serializer에 사용될 model, field지정
        model = UserModel
        # 모든 필드를 사용하고 싶을 경우 fields = "__all__"로 사용
        fields = ["username", "password", "fullname", "email", "userprofile"]
        extra_kwargs = {
            'password':{'write_only':True},
        }

여기서 유심히 봐야할건 각 시리얼라이즈들의 객체를 어떻게 선언하는지 보자. 맨 아래 User의 시리얼라이즈를 보면 일대일로 연결된 프로필 시리얼라이즈 객체를 가져오는것을 볼 수 있다. 해당 객체 즉 하용운 유저의 프로필 객체를 불러와 필드로 넣었다. 그러면 이제 해당 객체의 클래스를 봐보자! UserProfile클래스에는 hobby 라는 변수에 hobbyserializer 객체가 있고 그게 취미 필드에 값으로 선언 되었다. 그렇다면 위로 가서 hobby시리얼라이즈 클래스를 타고가 보면 역참조 즉, 하용운의 취미에 해당하는 각 각의 객체를 통해 우리는 그와 관련된 사람들을 가져와야한다. 이에 해당하는 값들을 필드로 넣어줘야하는데, 그러기 위해 serializers.SerializerMethod를 사용하면 된다. 이는 get_(시리얼라이즈메소드 객체를 담은 변수이름) 하여 함수이름을 작성하면 이에 반환되는 값이 해당 변수의 이름으로 필드 값으로 지정해줄 수 있다. 

 

설명이 장황했지만, 하용운에 대한 모든 정보 하용운 객체 -> 프로필 객체 -> 취미 객체 -> 다시 프로필 정보 로 연결되어 모든 정보를 볼 수 있다. 

 

  • 참조할 때, related_name 을 설정하는 이유는 외래키가 다수이면서 역참조를 할 경우 어떤걸 참조하고잇는지 구분하기 위해 따로 related_name을 사용하여 이름을 구분지을 수 있다.

참조하고 잇는 필드가 여러개인 상황