본문 바로가기
기록/TIL

[TIL] 231102 - 데브코스 18일차

by 투말치 2023. 11. 2.

목차

    반응형

    학습 내용

    Django - User

    - USer 생성 : Form 사용 / Serializer 사용

    - User 권한 관리

    - 상속 메소드 오버라이딩

    - Postman을 사용해 로그인한 상태로 요청 보내기

     

     

    새로 알게 된 것

     

    ForeignKey의 related_name 속성

    역방향으로 연결된 객체에서 해당 객체에 접근할 때 사용하는 이름을 지정할 수 있는 속성이다.

    class Question(models.Model):
        # ...
        owner = models.ForeignKey('auth.User', related_name='questions', on_delete=models.CASCADE, null=True)
    
    class Choice(models.Model):
        question = models.ForeignKey(Question, on_delete=models.CASCADE)

     

    사용자 측에서 Question에 접근할 때 user.questions.all() 형태로 접근할 수 있다.

    related_name을 지정하지 않으면 question.choice_set.all() 형태로 접근해야 한다.

     

    Serializer에서 외래키 표현 : PrimaryKeyRelatedField

    class UserSerializer(serializers.ModelSerializer):
        questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())

     

    여기서 many=True를 꼭 설정해야 한다. User는 여러 개의 Question을 가질 수 있는 일대다 관계이기 때문에 이를 명시해야 한다.

    그리고 questions를 정의하는 이유는 User 테이블에는 Question 정보가 없기 때문이다.

     

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

     

    Serializer relations - Django REST framework

    relations.py Data structures, not algorithms, are central to programming. — Rob Pike Relational fields are used to represent model relationships. They can be applied to ForeignKey, ManyToManyField and OneToOneField relationships, as well as to reverse re

    www.django-rest-framework.org

     

    User 생성

    1. Form 사용

    - 장고에서 제공하는 UserCreationForm을 사용해 구현한다.

     

    2. Serializer 사용

    Serializer를 사용해 구현하는 이유 : API 서버를 구현하기 위해서

    [ 구현과정 ]

    - RegisterSerializer 생성

    - Password 유효성 검사를 위해 유효성 검사 함수 정의

    - Password의 일치 여부를 위해 추가적으로 password2 변수 생성

    - 기존 User 모델에는 password2 변수가 없기 때문에 새로 create 함수 정의

     

    User 권한 관리

    Django REST framework에서 접근 권한을 관리할 수 있는 permissions를 제공한다.

    실습에서는 읽는 것은 누구나 가능하지만, 수정 요청을 할 때는 owner와 로그인 user가 일치하는지 확인하는 과정이 필요했다. 그래서 따로 permissions를 정의해주었다.

    class IsOwnerOrReadOnly(permissions.BasePermission):
        def has_object_permission(self, request, view, obj):
            if request.method in permissions.SAFE_METHODS:
                return True
            return obj.owner == request.user

     

    - SAFE_METHODS : GET, HEAD, OPTIONS -> 읽는 것은 허용한다는 뜻

     

    perform_create 함수에 대해서

     

    class QuestionList(generics.ListCreateAPIView):
    
        queryset = Question.objects.all()
        serializer_class = QuestionSerializer
        permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    
        def perform_create(self, serializer):
            serializer.save(owner=self.request.user)

     

    perform_create에서 serializer.save를 할 때 owner를 사용하는데, QuestionSerializer에서 owner는 readonly 필드다.

    이게 사용가능한 이유는 save를 할 때는 read_only 여부와 상관없이 주어진 필드를 그냥 사용하기 때문이다.

     

     

    궁금한 점

     

    Question 모델에서 외래키를 정의할 때는 클래스 명을 문자열로 작성했는데, 이전에 정의한 Choice에서는 외래키를 정의할 때 객체를 사용했다. 둘 다 사용이 가능한건가 궁금해서 찾아봤다.

    class Question(models.Model):
        # ...
        owner = models.ForeignKey('auth.User', related_name='questions', on_delete=models.CASCADE, null=True)
    
    class Choice(models.Model):
        question = models.ForeignKey(Question, on_delete=models.CASCADE)

     

     

    우선 장고 공식 문서에서는 다음과 같이 ForeignKey 필드에 대해서 설명하고 있다.

     

    "Many-to-One 관계. 두 개의 위치 인수가 필요합니다: 모델이 관련된 클래스와 on_delete 옵션입니다. 재귀적 관계를 만들려면 – 자신과 다대일 관계를 갖는 객체 – models.ForeignKey('self', on_delete=models.CASCADE)를 사용하세요. 아직 정의되지 않은 모델에서 관계를 만들어야 하는 경우 모델 객체 대신 모델의 이름을 사용할 수 있습니다."

     

    여기서 아직 정의되지 않은 모델에서 관계를 만들어야 하는 경우 모델 객체 대신 모델의 이름을 사용할 수 있다고 말하고 있다. 

    그렇다면 우리는 이미 장고에서 제공하고 있는 User 모델을 사용하는 것이니까 모델 객체를 사용해도 된다.

     

    from django.contrib.auth.models import User
    
    class Question(models.Model):
    	# ...
        owner = models.ForeignKey(User, related_name='questions', on_delete=models.CASCADE, null=True)

     

    다음과 같이 변경해서 잘 동작하는지 확인해본 결과, 잘 동작한다.

    model 파일을 변경했으니 혹시 몰라 마이그레이션도 해봤는데, No changes detected라고 떴다.

     

     

     

    https://docs.djangoproject.com/en/3.2/ref/models/fields/#foreignkey

     

    Django

    The web framework for perfectionists with deadlines.

    docs.djangoproject.com

     

     

     

    느낀 점

    permission을 따로 만들어서 원하는 권한으로 만드는 실습을 하면서 무엇이든 직접 만들어서 사용할 수 있다는 것을 느낄 수 있었다.

    반응형

    '기록 > TIL' 카테고리의 다른 글

    [TIL] 231108 - 데브코스 24일차  (0) 2023.11.08
    [TIL] 231107 - 데브코스 23일차  (5) 2023.11.07
    [TIL] 231101 - 데브코스 17일차  (1) 2023.11.01
    [TIL] 231031 - 데브코스 16일차  (0) 2023.10.31
    [TIL] 231030 - 데브코스 15일차  (0) 2023.10.30