I am currently working on a mentor-mentee matching service using Django DRF. I have made a ‘users’ app and have completed creating users&logging in. But I can’t edit user info using PUT method.
Here are my project files (models.py, serializers.py, views.py, urls.py, settings.py)
1. models.py
<code># users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
class User(AbstractUser):
is_mentor = models.BooleanField(default=False)
profile_pic = models.ImageField(upload_to='profile_pics/', default = 'default.png') # profile_pic dir 만들기, default이미지 업로드하기, 사진 첨부 루트 만들기
name = models.CharField(max_length=50, verbose_name= ("이름"))
birth_date = models.DateField(verbose_name= ("생년월일"), null=True, blank=True)
agreed_to_terms = models.BooleanField(default=False, verbose_name= ("이용약관 동의"))
@property
def role(self):
return "Mentor" if self.is_mentor else "Mentee"
class Interest(models.Model):
INTEREST_CHOICES = (
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
)
name = models.CharField(max_length=20, choices=INTEREST_CHOICES, unique=True)
def __str__(self):
return self.get_name_display()
class Mentor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentor')
interests = models.ManyToManyField(Interest, through='MentorInterest')
rating = models.FloatField(default=0, validators=[MinValueValidator(0), MaxValueValidator(5)])
total_ratings = models.PositiveIntegerField(default=0)
def clean(self):
super().clean()
if self.interests.count() > 3:
raise ValidationError("mentors can choose under 3 interest.")
def update_rating(self, new_rating):
self.rating = ((self.rating * self.total_ratings) + new_rating) / (self.total_ratings + 1)
self.total_ratings += 1
self.save()
class MentorInterest(models.Model):
mentor = models.ForeignKey(Mentor, on_delete=models.CASCADE)
interest = models.ForeignKey(Interest, on_delete=models.CASCADE)
class Meta:
unique_together = ('mentor', 'interest')
def __str__(self):
return f'{self.mentor.user.username} - {self.interest.name}'
class Mentee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentee')
</code>
<code># users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
class User(AbstractUser):
is_mentor = models.BooleanField(default=False)
profile_pic = models.ImageField(upload_to='profile_pics/', default = 'default.png') # profile_pic dir 만들기, default이미지 업로드하기, 사진 첨부 루트 만들기
name = models.CharField(max_length=50, verbose_name= ("이름"))
birth_date = models.DateField(verbose_name= ("생년월일"), null=True, blank=True)
agreed_to_terms = models.BooleanField(default=False, verbose_name= ("이용약관 동의"))
@property
def role(self):
return "Mentor" if self.is_mentor else "Mentee"
class Interest(models.Model):
INTEREST_CHOICES = (
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
)
name = models.CharField(max_length=20, choices=INTEREST_CHOICES, unique=True)
def __str__(self):
return self.get_name_display()
class Mentor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentor')
interests = models.ManyToManyField(Interest, through='MentorInterest')
rating = models.FloatField(default=0, validators=[MinValueValidator(0), MaxValueValidator(5)])
total_ratings = models.PositiveIntegerField(default=0)
def clean(self):
super().clean()
if self.interests.count() > 3:
raise ValidationError("mentors can choose under 3 interest.")
def update_rating(self, new_rating):
self.rating = ((self.rating * self.total_ratings) + new_rating) / (self.total_ratings + 1)
self.total_ratings += 1
self.save()
class MentorInterest(models.Model):
mentor = models.ForeignKey(Mentor, on_delete=models.CASCADE)
interest = models.ForeignKey(Interest, on_delete=models.CASCADE)
class Meta:
unique_together = ('mentor', 'interest')
def __str__(self):
return f'{self.mentor.user.username} - {self.interest.name}'
class Mentee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentee')
</code>
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
class User(AbstractUser):
is_mentor = models.BooleanField(default=False)
profile_pic = models.ImageField(upload_to='profile_pics/', default = 'default.png') # profile_pic dir 만들기, default이미지 업로드하기, 사진 첨부 루트 만들기
name = models.CharField(max_length=50, verbose_name= ("이름"))
birth_date = models.DateField(verbose_name= ("생년월일"), null=True, blank=True)
agreed_to_terms = models.BooleanField(default=False, verbose_name= ("이용약관 동의"))
@property
def role(self):
return "Mentor" if self.is_mentor else "Mentee"
class Interest(models.Model):
INTEREST_CHOICES = (
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
)
name = models.CharField(max_length=20, choices=INTEREST_CHOICES, unique=True)
def __str__(self):
return self.get_name_display()
class Mentor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentor')
interests = models.ManyToManyField(Interest, through='MentorInterest')
rating = models.FloatField(default=0, validators=[MinValueValidator(0), MaxValueValidator(5)])
total_ratings = models.PositiveIntegerField(default=0)
def clean(self):
super().clean()
if self.interests.count() > 3:
raise ValidationError("mentors can choose under 3 interest.")
def update_rating(self, new_rating):
self.rating = ((self.rating * self.total_ratings) + new_rating) / (self.total_ratings + 1)
self.total_ratings += 1
self.save()
class MentorInterest(models.Model):
mentor = models.ForeignKey(Mentor, on_delete=models.CASCADE)
interest = models.ForeignKey(Interest, on_delete=models.CASCADE)
class Meta:
unique_together = ('mentor', 'interest')
def __str__(self):
return f'{self.mentor.user.username} - {self.interest.name}'
class Mentee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='mentee')
2. serializers.py
<code># serializers.py
from rest_framework import serializers
from .models import User, Mentor, Mentee, Interest, MentorInterest
class InterestSerializer(serializers.ModelSerializer):
class Meta:
model = Interest
fields = ['name']
class MentorSerializer(serializers.ModelSerializer):
# Write-only field to receive interests as choice names
interests = serializers.ListField(
child=serializers.ChoiceField(choices=[choice[0] for choice in Interest.INTEREST_CHOICES]), # 선택 항목의 키 값만 사용
write_only=True
)
# Read-only field to display interests
interests_display = InterestSerializer(source='interests', many=True, read_only=True)
class Meta:
model = Mentor
fields = [
'interests',
'interests_display',
'rating',
'total_ratings'
]
def validate_interests(self, value):
if len(value) > 3:
raise serializers.ValidationError("멘토는 3개 이하의 관심사를 선택할 수 있습니다.")
# Check if each interest exists in the database
for interest_name in value:
if not Interest.objects.filter(name=interest_name).exists():
raise serializers.ValidationError(f"관심사 '{interest_name}'가 유효하지 않습니다.")
return value
class MenteeSerializer(serializers.ModelSerializer):
class Meta:
model = Mentee
fields = []
class UserSerializer(serializers.ModelSerializer):
mentor_profile = MentorSerializer(required=False)
mentee_profile = MenteeSerializer(required=False)
class Meta:
model = User
fields = [
'id',
'username',
'email',
'password',
'is_mentor',
'name',
'birth_date',
'profile_pic',
'agreed_to_terms',
'mentor_profile',
'mentee_profile'
]
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
# Extract nested profile data
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# Create user object with hashed password
user = User.objects.create_user(**validated_data)
# Handle mentor creation
if user.is_mentor and mentor_data:
interests_data = mentor_data.pop('interests', [])
mentor = Mentor.objects.create(user=user, **mentor_data)
# Set up interests through MentorInterest
for interest_name in interests_data:
interest = Interest.objects.get(name=interest_name)
MentorInterest.objects.create(mentor=mentor, interest=interest)
# Handle mentee creation
elif not user.is_mentor and mentee_data:
# 멘티는 카테고리를 설정하지 않는다는 새로운 설정!
Mentee.objects.create(user=user, **mentee_data)
return user
def update(self, instance, validated_data):
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# 유저 속성들 업데이트 (차후에 업데이트 가능한 속성을 더 넣고 싶다면 추가 가능)
instance.name = validated_data.get('name', instance.name)
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.profile_pic = validated_data.get('profile_pic', instance.profile_pic)
instance.save()
# Update mentor profile if the user is a mentor
if instance.is_mentor and mentor_data:
mentor_serializer = MentorSerializer(instance.mentor_profile, data=mentor_data, partial=True)
if mentor_serializer.is_valid():
mentor_serializer.save()
# Update mentee profile if the user is not a mentor
elif not instance.is_mentor and mentee_data:
mentee_serializer = MenteeSerializer(instance.mentee_profile, data=mentee_data, partial=True)
if mentee_serializer.is_valid():
mentee_serializer.save()
return instance
</code>
<code># serializers.py
from rest_framework import serializers
from .models import User, Mentor, Mentee, Interest, MentorInterest
class InterestSerializer(serializers.ModelSerializer):
class Meta:
model = Interest
fields = ['name']
class MentorSerializer(serializers.ModelSerializer):
# Write-only field to receive interests as choice names
interests = serializers.ListField(
child=serializers.ChoiceField(choices=[choice[0] for choice in Interest.INTEREST_CHOICES]), # 선택 항목의 키 값만 사용
write_only=True
)
# Read-only field to display interests
interests_display = InterestSerializer(source='interests', many=True, read_only=True)
class Meta:
model = Mentor
fields = [
'interests',
'interests_display',
'rating',
'total_ratings'
]
def validate_interests(self, value):
if len(value) > 3:
raise serializers.ValidationError("멘토는 3개 이하의 관심사를 선택할 수 있습니다.")
# Check if each interest exists in the database
for interest_name in value:
if not Interest.objects.filter(name=interest_name).exists():
raise serializers.ValidationError(f"관심사 '{interest_name}'가 유효하지 않습니다.")
return value
class MenteeSerializer(serializers.ModelSerializer):
class Meta:
model = Mentee
fields = []
class UserSerializer(serializers.ModelSerializer):
mentor_profile = MentorSerializer(required=False)
mentee_profile = MenteeSerializer(required=False)
class Meta:
model = User
fields = [
'id',
'username',
'email',
'password',
'is_mentor',
'name',
'birth_date',
'profile_pic',
'agreed_to_terms',
'mentor_profile',
'mentee_profile'
]
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
# Extract nested profile data
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# Create user object with hashed password
user = User.objects.create_user(**validated_data)
# Handle mentor creation
if user.is_mentor and mentor_data:
interests_data = mentor_data.pop('interests', [])
mentor = Mentor.objects.create(user=user, **mentor_data)
# Set up interests through MentorInterest
for interest_name in interests_data:
interest = Interest.objects.get(name=interest_name)
MentorInterest.objects.create(mentor=mentor, interest=interest)
# Handle mentee creation
elif not user.is_mentor and mentee_data:
# 멘티는 카테고리를 설정하지 않는다는 새로운 설정!
Mentee.objects.create(user=user, **mentee_data)
return user
def update(self, instance, validated_data):
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# 유저 속성들 업데이트 (차후에 업데이트 가능한 속성을 더 넣고 싶다면 추가 가능)
instance.name = validated_data.get('name', instance.name)
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.profile_pic = validated_data.get('profile_pic', instance.profile_pic)
instance.save()
# Update mentor profile if the user is a mentor
if instance.is_mentor and mentor_data:
mentor_serializer = MentorSerializer(instance.mentor_profile, data=mentor_data, partial=True)
if mentor_serializer.is_valid():
mentor_serializer.save()
# Update mentee profile if the user is not a mentor
elif not instance.is_mentor and mentee_data:
mentee_serializer = MenteeSerializer(instance.mentee_profile, data=mentee_data, partial=True)
if mentee_serializer.is_valid():
mentee_serializer.save()
return instance
</code>
# serializers.py
from rest_framework import serializers
from .models import User, Mentor, Mentee, Interest, MentorInterest
class InterestSerializer(serializers.ModelSerializer):
class Meta:
model = Interest
fields = ['name']
class MentorSerializer(serializers.ModelSerializer):
# Write-only field to receive interests as choice names
interests = serializers.ListField(
child=serializers.ChoiceField(choices=[choice[0] for choice in Interest.INTEREST_CHOICES]), # 선택 항목의 키 값만 사용
write_only=True
)
# Read-only field to display interests
interests_display = InterestSerializer(source='interests', many=True, read_only=True)
class Meta:
model = Mentor
fields = [
'interests',
'interests_display',
'rating',
'total_ratings'
]
def validate_interests(self, value):
if len(value) > 3:
raise serializers.ValidationError("멘토는 3개 이하의 관심사를 선택할 수 있습니다.")
# Check if each interest exists in the database
for interest_name in value:
if not Interest.objects.filter(name=interest_name).exists():
raise serializers.ValidationError(f"관심사 '{interest_name}'가 유효하지 않습니다.")
return value
class MenteeSerializer(serializers.ModelSerializer):
class Meta:
model = Mentee
fields = []
class UserSerializer(serializers.ModelSerializer):
mentor_profile = MentorSerializer(required=False)
mentee_profile = MenteeSerializer(required=False)
class Meta:
model = User
fields = [
'id',
'username',
'email',
'password',
'is_mentor',
'name',
'birth_date',
'profile_pic',
'agreed_to_terms',
'mentor_profile',
'mentee_profile'
]
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
# Extract nested profile data
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# Create user object with hashed password
user = User.objects.create_user(**validated_data)
# Handle mentor creation
if user.is_mentor and mentor_data:
interests_data = mentor_data.pop('interests', [])
mentor = Mentor.objects.create(user=user, **mentor_data)
# Set up interests through MentorInterest
for interest_name in interests_data:
interest = Interest.objects.get(name=interest_name)
MentorInterest.objects.create(mentor=mentor, interest=interest)
# Handle mentee creation
elif not user.is_mentor and mentee_data:
# 멘티는 카테고리를 설정하지 않는다는 새로운 설정!
Mentee.objects.create(user=user, **mentee_data)
return user
def update(self, instance, validated_data):
mentor_data = validated_data.pop('mentor_profile', None)
mentee_data = validated_data.pop('mentee_profile', None)
# 유저 속성들 업데이트 (차후에 업데이트 가능한 속성을 더 넣고 싶다면 추가 가능)
instance.name = validated_data.get('name', instance.name)
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.birth_date = validated_data.get('birth_date', instance.birth_date)
instance.profile_pic = validated_data.get('profile_pic', instance.profile_pic)
instance.save()
# Update mentor profile if the user is a mentor
if instance.is_mentor and mentor_data:
mentor_serializer = MentorSerializer(instance.mentor_profile, data=mentor_data, partial=True)
if mentor_serializer.is_valid():
mentor_serializer.save()
# Update mentee profile if the user is not a mentor
elif not instance.is_mentor and mentee_data:
mentee_serializer = MenteeSerializer(instance.mentee_profile, data=mentee_data, partial=True)
if mentee_serializer.is_valid():
mentee_serializer.save()
return instance
3. views.py
<code>from django.shortcuts import render
# 회원가입
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from .models import User, Mentor, Mentee, Interest
from .serializers import UserSerializer, MentorSerializer, MenteeSerializer, InterestSerializer
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.views import APIView
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
# 사용자에 대한 추가 정보를 JWT 페이로드에 포함
data['user_id'] = self.user.id
data['username'] = self.user.username
data['is_mentor'] = self.user.is_mentor
data['name'] = self.user.name
return data
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
# 로그아웃 뷰
class LogoutView(APIView):
permission_classes = [IsAuthenticated] # 로그인된 사용자만 접근 가능
def post(self, request):
# Refresh 토큰을 요청 데이터에서 추출
refresh_token = request.data.get("refresh")
if not refresh_token:
return Response({"detail": "Refresh token is required."}, status=status.HTTP_400_BAD_REQUEST)
try:
# RefreshToken 객체 생성 및 블랙리스트에 추가
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def get_permissions(self):
if self.action == 'create':
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
if response.status_code == status.HTTP_201_CREATED:
response.data['message'] = "User created successfully!"
return response
def update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 수정 성공"
return response
def partial_update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().partial_update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 부분 수정 성공"
return response
</code>
<code>from django.shortcuts import render
# 회원가입
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from .models import User, Mentor, Mentee, Interest
from .serializers import UserSerializer, MentorSerializer, MenteeSerializer, InterestSerializer
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.views import APIView
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
# 사용자에 대한 추가 정보를 JWT 페이로드에 포함
data['user_id'] = self.user.id
data['username'] = self.user.username
data['is_mentor'] = self.user.is_mentor
data['name'] = self.user.name
return data
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
# 로그아웃 뷰
class LogoutView(APIView):
permission_classes = [IsAuthenticated] # 로그인된 사용자만 접근 가능
def post(self, request):
# Refresh 토큰을 요청 데이터에서 추출
refresh_token = request.data.get("refresh")
if not refresh_token:
return Response({"detail": "Refresh token is required."}, status=status.HTTP_400_BAD_REQUEST)
try:
# RefreshToken 객체 생성 및 블랙리스트에 추가
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def get_permissions(self):
if self.action == 'create':
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
if response.status_code == status.HTTP_201_CREATED:
response.data['message'] = "User created successfully!"
return response
def update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 수정 성공"
return response
def partial_update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().partial_update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 부분 수정 성공"
return response
</code>
from django.shortcuts import render
# 회원가입
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from .models import User, Mentor, Mentee, Interest
from .serializers import UserSerializer, MentorSerializer, MenteeSerializer, InterestSerializer
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.views import APIView
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
data = super().validate(attrs)
# 사용자에 대한 추가 정보를 JWT 페이로드에 포함
data['user_id'] = self.user.id
data['username'] = self.user.username
data['is_mentor'] = self.user.is_mentor
data['name'] = self.user.name
return data
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
# 로그아웃 뷰
class LogoutView(APIView):
permission_classes = [IsAuthenticated] # 로그인된 사용자만 접근 가능
def post(self, request):
# Refresh 토큰을 요청 데이터에서 추출
refresh_token = request.data.get("refresh")
if not refresh_token:
return Response({"detail": "Refresh token is required."}, status=status.HTTP_400_BAD_REQUEST)
try:
# RefreshToken 객체 생성 및 블랙리스트에 추가
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_205_RESET_CONTENT)
except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def get_permissions(self):
if self.action == 'create':
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
def create(self, request, *args, **kwargs):
response = super().create(request, *args, **kwargs)
if response.status_code == status.HTTP_201_CREATED:
response.data['message'] = "User created successfully!"
return response
def update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 수정 성공"
return response
def partial_update(self, request, *args, **kwargs):
# 본인만 자신의 정보를 업데이트할 수 있도록 함
if request.user.id != kwargs.get('pk'):
return Response({"detail": "로그인 후 정보 수정하시길 바랍니다."}, status=status.HTTP_403_FORBIDDEN)
response = super().partial_update(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
response.data['message'] = "유저 정보 부분 수정 성공"
return response
4. urls.py
(project/urls.py)
<code>from django.contrib import admin
from django.urls import path, include
# ImageField를 위해
from django.conf import settings
from django.conf.urls.static import static
# 로그인을 위해
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), # 토큰 갱신 엔드포인트
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
</code>
<code>from django.contrib import admin
from django.urls import path, include
# ImageField를 위해
from django.conf import settings
from django.conf.urls.static import static
# 로그인을 위해
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), # 토큰 갱신 엔드포인트
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
</code>
from django.contrib import admin
from django.urls import path, include
# ImageField를 위해
from django.conf import settings
from django.conf.urls.static import static
# 로그인을 위해
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
)
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include('users.urls')),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), # 토큰 갱신 엔드포인트
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
(users/urls.py)
<code>
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, CustomTokenObtainPairView, LogoutView
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('logout/', LogoutView.as_view(), name='logout'), # 로그아웃 엔드포인트
]
</code>
<code>
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, CustomTokenObtainPairView, LogoutView
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('logout/', LogoutView.as_view(), name='logout'), # 로그아웃 엔드포인트
]
</code>
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, CustomTokenObtainPairView, LogoutView
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('login/', CustomTokenObtainPairView.as_view(), name='token_obtain_pair'), # 로그인 엔드포인트
path('logout/', LogoutView.as_view(), name='logout'), # 로그아웃 엔드포인트
]
Also I put a file in Migration folder to initialize Interests
<code># Generated by Django 5.0.7 on 2024-07-29 12:38
# users/migrations/0002_add_initial_interests.py
from django.db import migrations
def create_initial_interests(apps, schema_editor):
Interest = apps.get_model('users', 'Interest')
interests = [
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
]
for name, display_name in interests:
Interest.objects.get_or_create(name=name)
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.RunPython(create_initial_interests),
]
</code>
<code># Generated by Django 5.0.7 on 2024-07-29 12:38
# users/migrations/0002_add_initial_interests.py
from django.db import migrations
def create_initial_interests(apps, schema_editor):
Interest = apps.get_model('users', 'Interest')
interests = [
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
]
for name, display_name in interests:
Interest.objects.get_or_create(name=name)
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.RunPython(create_initial_interests),
]
</code>
# Generated by Django 5.0.7 on 2024-07-29 12:38
# users/migrations/0002_add_initial_interests.py
from django.db import migrations
def create_initial_interests(apps, schema_editor):
Interest = apps.get_model('users', 'Interest')
interests = [
('belief', '가치관'),
('finance', '재테크'),
('love', '사랑'),
('daily', '생활 지식'),
('relationship', '인간 관계'),
('career', '진로'),
]
for name, display_name in interests:
Interest.objects.get_or_create(name=name)
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.RunPython(create_initial_interests),
]
I have…
- Logged into the user that I wanted to change info : /users/login/
- Copied the access token and put it in the Authorization header
- /users/users/<user_id>/ using PUT method gave me 403 error
New contributor
coals is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.