djangro serializer 개인적인복습 , 스터디

김하진·2022년 6월 23일
0

어제 til을 깜빡 했다 .. 그것도 그렇고 머리가 너무 아팠다
단기간에 너무 많은 것을 배울려하니 머리도 더이상 안돌아가고 컨디션도 급격히 나빠진 느낌이라 어제밤에는 거의 기절하듯이 잠을 잔 것 같다..

serialzier 가 보기에는 편해보이지만, 제대로 사용하려면 개념과 원리를 정확하게 알아야한다. django는 조금이라도 어긋나면 바로 오류를 뱉기 때문에, 정확한 데이터를 주고 받아야 한다.

우선 model 설정 부터 잘 연결을 해줘야 하고 serializer를 사용할때 모델을 보면서 관계를 정확하게 파악하고 코딩을 해줘야한다! 안그럼 정말 밑도끝도없이 꼬인다

https://github.com/haajinkim/django_rpac

오늘 저녁에 개인적으로 복습겸 작업을 조금 진행 했었다. 오늘은 전체적인 정리와 복습이 필요 한 것 같다.

model

class Blog(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE)
    category = models.ForeignKey('Category',on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    desc = models.TextField()
    create_date = models.DateTimeField(auto_now=True)
    edit_date = models.DateTimeField(auto_now=True)
    exposure_end = models.DateTimeField(auto_now_add=False)

class Category(models.Model):
    category = models.CharField(max_length=50)

class Comment(models.Model):
    user = models.ForeignKey(User,on_delete=models.CASCADE)
    title = models.ForeignKey(Blog,on_delete=models.CASCADE)
    create_date = models.DateTimeField(auto_now=True)
    desc = models.CharField(max_length=50)

우선 Blog , Category ,Comment 라는 모델을 만들었다.
모델간의 관계를 보자면 blgo 가 category 를 정참조 하고 comment가 Categrory 를 정참조한다

serialzier

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model =Category
        fields = ["category"]

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields =["title","create_date","desc"]


class BlogSerializer(serializers.ModelSerializer):
    category =CategorySerializer()
    comment =serializers.SerializerMethodField()
    user = serializers.SerializerMethodField()
    def get_comment(self,obj):
        comment_list =[{"comment_desc":comment.desc} for comment in obj.comment_set.all()]
        print(comment_list)
        return comment_list
    def get_user(self,obj):
        return obj.user.username
    class Meta:
        model = Blog
        fields = ["user","category","comment","title","desc","create_date","edit_date",
                        "edit_date","exposure_end"]

blog 에서 category, comment 를 전부 가져오려면 생각을 좀 해야한다. 우선 blog 에서 category 는 연결 해주면 바로 가져 올 수 있다. blog model 안에 category 가 존재하기 때문이다. 하지만 여기서 comment 를 가져오려면? 에러가 발생한다.
blog 모델에는 comment 가 없기때문이다. 그래서 comment 를 serializerMethofiedl()필드로 만들어 주고
함수의 obj 를 이용해서 가져올 수 있다. dir(obj)을 해보면 comment_set 이 나온다 (역참조) , relate_name 없이도 바로 역참조 조회가 가능하다. 리스트 컴프리헨션을 이용해서 json 형태로 만들어준뒤 리턴시켜서 넣어주면 조회가 가능하다!
이개념이 시리얼라이즈에서 굉장히 어려웠고 지금도 많이 헷갈리는 개념이다. 개속 반복하면서 연습하는 방법 밖에 없는 것 같다!
다른 모델로 예를 들자면

    # 1. obj 을 통해 TagModel object 를 가져온다.
    # 2. obj.postmodel_set.all()으로 역참조를 해서 postmodel의 객체를 쿼리셋으로 모두 가져 온다. 
    # (post -> tag 정참조) (tag -> post) 역참조 tag에는 tag_names 라는 필드밖에 없으니.
    # 3. 원하는 데이터만 출력하기위해 리스트 컴프리헨션 을 이용해서 최종출력값 => 
    # "author":postmodel.author.username, "content":postmodel.contetns 라는 값만 가져온다
    # postmodel => (쿼리셋=obj.postmodel_set.all()).content
    # postmodel => (쿼리셋=obj.postmodel_set.all()).author.username 
    # author.username 은 postmodel에 .author를 조회하면 Usermodel과의 포링키 이기 때문에
    # .username 을 통해서 조회한다(정참조.)

loign,logout

class Loginview(APIView):
    def post(self, request):
        user = authenticate(request, **request.data)
        if user:
            login(request, user)
            return Response({"messge":"로그인 성공!"},status=status.HTTP_200_OK)

        return Response({"messge":"존재하지않는 사용자거나 비밀번호가 틀립니다!"},status=status.HTTP_400_BAD_REQUEST)
        
    def delete(self, request):
        logout(request)
        pass

class Userview(APIView):
    def get(self, request):
        pass
    def post(self, request):
        user_serializer = UserSerializer(data=request.data)
        user_serializer.is_valid(raise_exception=True)
        user_serializer.save()
        return Response(user_serializer.data,status=status.HTTP_200_OK)

로그인 로그아웃은 간단하게 구현이 가능하다. 비밀번호는 원래는 평면화 되서 들어가는데 그러면 로그인을 할 수가 없다.
해슁 되있는 비밀번호로 로그인을 해야 하기에

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["username","email","password","fullname"]

        extra_kwargs = {
            "password" : {"write_only": True}
        }

    def create(self, validated_data):
        password = validated_data.pop("password","")
        #받아온 데이터에서 password 만빼내서 따로저장
        user =User(**validated_data)
        user.set_password(password)
        user.save()
        return user

user.set_password 로 비밀번호를 수정해주고 저장을 하면 해슁된 비밀번호로 저장이 된다!
또한 extra_kwargs 를 통해서 리턴된 데이터를 안보이게 할 수 있다! 반대로 read_only 도 존재한다.
read_only 는 시리얼라이즈를 할때 데이터가 개속해서 생성되거나 수정되거나, 필수로 입력해야 하는 값들에 대한 오류가 있을 때 사용이 가능한 것 같다.

validate , create ,update 와 관련된 내용은 내일 개인적으로 작업을 진행해보고, 정리를 다시 해봐야겠다.

그리고 내일부터 주말동안 프론트와 연결하는 작업도 진행할 예정이다!!

profile
진킴

0개의 댓글