TIL) 데브코스 14일차 - Django(4)

Pori·2023년 11월 2일
0

데엔

목록 보기
9/47

User

Model의 Class에 소유권 추가하기

: Model의 각 클래스에 소유권을 추가하고 싶은 경우에 사용한다. 예제에서는 각 질문에 대하여 소유자를 확인 하도록 하는 필드를 생성하였다.

  • 외래키로 auth.User를 사용
    • user_id를 통해서 question을 가져올 수 있도록 하기위해 related_name을 사용해준다.
    • user가 제거되는 경우 question도 같이 제거되어야 하기 때문에 CASCADE를 적용한다.
owner = models.ForeignKey('auth.User',related_name='questions',on_delete=models.CASCADE, null =True)

사용자 Serializer 제작.

: User를 활용하여 다양한 동작을 하기 위해서는 통신이 필요하다. 이 때 사용되는 Serializer를 생성하고 View에 등록해준다.

# serializer.py
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
    # user의 pk를 통해서 여러개의 questions를 갖는다는 것을 명시.
    # question을 통해서 가져오기 때문에 다음처럼 사용
    questions = serializers.PrimaryKeyRelatedField(many=True, queryset=Question.objects.all())
    
    class Meta:
        model =User
        fields = ['id','username','questions']

#views.py
class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
💡 PrimaryKeyRelatedField에 대한 이해 : PrimaryKeyRelatedField는 기본 키를 사용하여 관계의 대상을 나타낼 수 있다. 이에 예시는 아래 코드와 같다.
class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

# 결과
{
    'album_name': 'Undun',
    'artist': 'The Roots',
    'tracks': [
        89,
        90,
        91,
        ...
    ]
}

참고 : https://www.django-rest-framework.org/api-guide/serializers/ (Django REST framework api guide)

User의 생성 - Form을 사용

: from django.contrib.auth.forms import UserCreationForm 을 활용하여 구현해준다.

from django.views import generic
from django.urls import reverse_lazy
from django.contrib.auth.forms import UserCreationForm

class SignupView(generic.CreateView):
    form_class = UserCreationForm
# reverse_lazy를 사용하여 다른 Path로 전송시킬 수 있다.
    success_url = reverse_lazy('user-list')
    template_name = 'registration/signup.html'

User의 생성 - Serializer을 사용

  1. serializers.py에 Serializer 클래스를 생성한다.
class RegisterSerializer(serializers.ModelSerializer):
	class Meta:
		model = User
		fields = ['username','password']
		extra_kwargs = {'password' : {'write_only':True}}
	
  1. Views.py에 view생성해주기
from polls_api.serializers import RegisterSerializer

class RegisterUser(generics.CreateAPIView):
    serializer_class = RegisterSerializer
  1. urls에 등록하기
path('register/', RegisterUser.as_view()),
  • Password-validatior 만들기
# 간단한 패스워드 막기
from django.contrib.auth.password_validation import validate_password

class RegisterSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
    password2 = serializers.CharField(write_only=True, required=True)
    
    def validate(self, attrs):
        if attrs['password'] != attrs['password2']:
            raise serializers.ValidationError({"password": "두 패스워드가 일치하지 않습니다."})
        return attrs
    
# 정상적으로 패스워드가 동일한 경우에 save를 해준다.
    def create(self, validated_data):
        user = User.objects.create(username=validated_data['username'])
        user.set_password(validated_data['password'])
        user.save()
        return user
    
    class Meta:
        model = User
        fields = ['username', 'password','password2']

권한 관리

: Question에 owner 필드를 넣어주었지만, 여전히 로그인 하지 않은경우, 소유자가 아닌 다른 계정의 경우에도 편집이 가능하다. 따라서 적절한 권한부여를 통해 이를 막아야한다.

  • api-auth path추가하기
# urls.py
path('api-auth/', include('rest_framework.urls'))
  • 로그인과 로그아웃 시 연결될 페이지를 설정하기
# settings.py에서 작업한다.
from django.urls import reverse_lazy
LOGIN_REDIRECT_URL = reverse_lazy('question-list')
LOGOUT_REDIRECT_URL = reverse_lazy('question-list')
  • QuestionSerializer를 변경하여 question 생성 시에 소유자 필드를 무조건 현재 로그인된 사용자로 변경
class QuestionSerializer(serializers.ModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')

    class Meta:
        model = Question
        fields = ['id', 'question_text', 'pub_date', 'owner']
  • 로그인 한 사용자만 수정하게 만드는 경우 rest_framework의 permission를 활용한다.
# Views.py
from rest_framework import generics,permissions
class QuestionList(generics.ListCreateAPIView):
	...
	permission_classes = [permissions.IsAuthenticatedOrReadOnly]
	def perform_create(self, serializer):
				# save 요청시에는 어떤 값이는 문제 없이 넣을 수 있다.
        serializer.save(owner=self.request.user) 
  • 추가로 Owner == user인 경우에만 API 요청이 가능하도록 하려면 다음과 같이 permission 코드를 작성한다.
from rest_framework import 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

: request.method가 SAFE_METHODS ('GET', 'HEAD', 'OPTIONS')에 포함되거나, obj의 user가 로그인 된 user와 같으면 API의 요청 결과를 볼 수 있다.

PostMan

실제 api가 동작하는 서버에서 로그인 정보없이 요청이 들어올 수 있다. 따라서 다양한 상황에 대하여 API서버를 테스트 해보아야 한다.

이를 PostMan이 수행해주는데 URL과 함께 API 동작을 지정해 줄 수 있고, Headers를 통해서 각 key를 입력 가능하다.

  • 로그인 테스트
    • Content-Type : application/json
    • Cookie : sessionid = …
  • put 테스트를 위해서는 SCRFToken과 이에 맞는 cookie값을 넣어주어야한다.


공부 한 내용

  • Django User추가
  • 권한 관리
  • PostMan

새롭게 배운 내용

  • Django에서 User를 다루는 방식
  • PostMan을 통해 API서버의 다양한 동작 환경다루기

느낀점&참고

: Form과 Serializer를 활용하여 User를 생성하고, 권한관리를 직접 해보면서 다양한 상황이 발생한 경우에 이에 대한 권한 처리가 중요하다는 것을 알게 된 것 같다. 더욱이 아직 다루어보지 못한 여러 기능에 대해서 공부가 더 필요하다 생각한다.

0개의 댓글