from rest_framework import generics, status, permissions from rest_framework.response import Response from rest_framework_simplejwt.tokens import RefreshToken # 用于登录时或注册后手动生成token # 从当前应用的 models.py 和 serializers.py 导入 from .models import CustomUser from .serializers import UserRegistrationSerializer, UserProfileSerializer class UserRegistrationView(generics.CreateAPIView): """ 用户注册视图。 允许任何人 (未认证用户) 访问此端点进行注册。 """ queryset = CustomUser.objects.all() # CreateAPIView 需要 queryset,即使我们不直接用它来过滤 serializer_class = UserRegistrationSerializer permission_classes = [permissions.AllowAny] # 明确允许任何人访问此视图 def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) # 如果数据无效,DRF会自动返回400错误和详细信息 user = serializer.save() # 调用 serializer 的 create 方法,创建用户 # 注册成功后,为用户生成JWT令牌 (实现注册即登录) refresh = RefreshToken.for_user(user) # 构建响应数据 # 我们使用 UserProfileSerializer 来序列化新创建的 user 对象,以便返回更完整的用户信息 # 需要传递 request 到 context 以便 UserProfileSerializer 中的 get_avatar_url 能构建完整URL user_data = UserProfileSerializer(user, context={'request': request}).data response_data = { 'refresh': str(refresh), 'access': str(refresh.access_token), 'user': user_data } return Response(response_data, status=status.HTTP_201_CREATED) class UserProfileView(generics.RetrieveUpdateAPIView): """ 获取和更新当前已认证用户的个人资料视图。 只允许已认证的用户访问他们自己的个人资料。 """ queryset = CustomUser.objects.all() # RetrieveUpdateAPIView 也需要 queryset serializer_class = UserProfileSerializer permission_classes = [permissions.IsAuthenticated] # 明确只有认证用户才能访问 def get_object(self): # 此方法返回视图将要操作的对象实例 # 在这里,我们返回当前发出请求的认证用户 return self.request.user # 当收到 PUT 或 PATCH 请求时,DRF的 RetrieveUpdateAPIView 会自动调用 # serializer_class 的 update() 或 partial_update() 方法。 # 我们在 UserProfileSerializer 中没有定义 update 方法,所以它会使用 # ModelSerializer 的默认 update 行为,这对于 ImageField (如 avatar) 通常是有效的。 # 如果需要更复杂的更新逻辑(例如,修改密码、验证邮箱/手机更改),则需要重写 update 方法。 # 为了让 UserProfileSerializer 中的 get_avatar_url 能正确工作, # 我们需要确保 serializer 在实例化时能获取到 request 对象。 # RetrieveUpdateAPIView 会自动将 request 传递给 serializer context。 # def get_serializer_context(self): # context = super().get_serializer_context() # context.update({"request": self.request}) # return context # 上面的 get_serializer_context 是DRF 3.9版本之后默认会做的,所以通常不需要显式重写。 # 但如果头像URL不正确,可以尝试取消注释上面这段代码。