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}}
2. Views.py에 view생성해주기
from polls_api.serializers import RegisterSerializer
class RegisterUser(generics.CreateAPIView):
serializer_class = RegisterSerializer
3. 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의 요청 결과를 볼 수 있다.
'Python > Django' 카테고리의 다른 글
Django - apscheduler (0) | 2024.03.15 |
---|---|
Django - Serializers, CRUD (0) | 2024.03.15 |
Django - View, template, form (0) | 2024.03.15 |
Django - 설치 및 기본 세팅 (2) | 2024.03.15 |