Как обновить профиль пользователя в Django с помощью Django REST API Framework?
【 Обзор системы】
В моей системе есть 5 различных типов пользователей (администраторы, сотрудники, клиенты, студенты и преподаватели). Клиент, владеющий собственным профилем, может обновлять информацию своего профиля. Он/она не имеет права обновлять информацию профиля других клиентов.
Я не получаю ожидаемый результат, как сказано выше.
models.py
Этот файл включает 2 модели (UserAccount и ClientProfile)
class UserAccount(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(verbose_name="Email Address", max_length=255, unique=True)
full_name = models.CharField(verbose_name="Full Name", max_length=255)
date_joined = models.DateTimeField(verbose_name="Member Since", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="Last Logged In", auto_now=True)
is_verified = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_client = models.BooleanField(default=False)
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["full_name", ]
objects = UserAccountManager()
class Meta:
db_table = 'USERS_INFORMATION'
verbose_name = "Users Account"
verbose_name_plural = "Users Accounts"
def __str__(self):
return self.full_name
def get_name(self):
return self.full_name
def get_email(self):
return self.email
class ClientProfile(models.Model):
class Meta:
db_table = 'CLIENTS_PROFILE_INFORMATION'
verbose_name = "Clients Profile Account"
verbose_name_plural = "Clients Profile Accounts"
client = models.OneToOneField(UserAccount, on_delete=models.CASCADE, related_name="client")
country = models.CharField(verbose_name="Country", max_length=100, blank=True, null=True)
is_client = models.BooleanField(default=True)
def __str__(self):
return self.client.full_name
def get_email(self):
return self.client.email
def get_dateJoined(self):
return self.client.date_joined
def get_lastLoggedIn(self):
return self.client.last_login
def get_isVerified(self):
return bool(self.client.is_verified)
get_isVerified.boolean = True
def get_country(self):
return self.country
get_email.short_description = "Email Address"
get_dateJoined.short_description = "Member Since"
get_lastLoggedIn.short_description = "Last Logged In"
get_isVerified.short_description = "Is Email Address Verified"
Я использую пользовательское разрешение, чтобы позволить владельцам клиентов получить доступ к их собственному профилю.
permissions.py
class ClientProfileUpdateViewPermission(BasePermission):
message = "Only Client who is the Owner of their profile can View / Edit their own Profile Information"
def has_object_permission(self, request, view, object):
if request.method in SAFE_METHODS:
return True
return object.id == request.user.id
Я использую RetrieveUpdateAPIView Generic Class Based View
class ClientProfileUpdateAPIView(RetrieveUpdateAPIView):
authentication_classes = (JWTAuthentication, )
permission_classes = (ClientProfileUpdateViewPermission, )
def get(self, request, client_id, format=None):
client_profile = ClientProfile.objects.get(client_id=client_id)
if client_profile.country == None:
client_profile.country = "-"
if client_profile.get_isVerified():
account_status = "Verified"
else:
account_status = "Not Verified"
client_profile_information = {
"Client Full Name" : client_profile.__str__(),
"Client Email Address" : client_profile.get_email(),
"Client Since" : client_profile.get_dateJoined(),
"Last Logged In" : client_profile.get_lastLoggedIn(),
"Country" : client_profile.get_country(),
"Account Status" : account_status,
}
return Response(client_profile_information, status=HTTP_200_OK)
urls.py
path("clients/<int:client_id>/update", ClientProfileUpdateAPIView.as_view(), name="client-profile-update"),
Я использую Postman Agent для тестирования API. Я также использую простую аутентификацию и авторизацию пользователей JWT, поэтому передаю Authorization Bearer <token>
также в Postman Agent.
Для клиента ID: 26 я получаю токен и передаю его в секции Header как Authorization Bearer, и когда я отправляю запрос для всех различных 3 клиентов (ID: 3, 6, 26), я получаю всю информацию о других клиентах. Но я хочу обновить только ID клиента 26. Для клиентов ID: 3 и 6, будет получен ответ Forbidden Response.
Я знаю, что эта работа еще не завершена. Но я хочу решить эту проблему. Жду вашей поддержки.
Думаю, вам следует использовать from rest_framework.viewsets import GenericViewSet
кроме того, вы не должны отправлять id клиента в параметрах запроса подобным образом.
вы можете использовать пользовательское действие с помощью декоратора @action(...)
из rest_framework.decorators
для обеспечения действия PUT
без параметров запроса.
примерно так:
@action(detail=False, methods=['put'])
def me(self, request, *args, **kwargs):
instance = request.user
serializer = self.get_serializer(data=request.data, instance=instance, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
data = {"message": "your profile updated successfully"}
return Response(data=data, status=status.HTTP_200_OK)
и ваш URL будет выглядеть следующим образом: user/me
в urls.py
При таком подходе вам не нужно будет проверять пользователя, если он/она хочет обновить чужой профиль, больше никакого кода