Django中如何用序列化器替换表单实现用户注册登录API?
Got it, let's convert your existing form-based registration and login views into REST APIs using Django REST Framework (DRF). Here's a step-by-step solution that preserves your original business logic while following REST best practices:
1. First, Tweak Your Serializers (for Security & Correctness)
First, update your UserSerializer to mark the password as write_only — this ensures the password is never returned in API responses, which is a critical security practice:
# Serializer.py from rest_framework import serializers from django.contrib.auth.models import User from .models import UserProfileInfo class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) # Add this line class Meta(): model = User fields = ('username','email','password') class UserProfileSerializer(serializers.ModelSerializer): class Meta(): model = UserProfileInfo fields = ('phone_no',)
2. Create the Registration API View
Replace your existing register function view with a DRF APIView class. This handles POST requests to create both a User and linked UserProfileInfo:
# views.py from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate from rest_framework.authtoken.models import Token from .serializers import UserSerializer, UserProfileSerializer from .models import UserProfileInfo class RegisterAPIView(APIView): def post(self, request): # Validate incoming data against both serializers user_serializer = UserSerializer(data=request.data) profile_serializer = UserProfileSerializer(data=request.data) if user_serializer.is_valid() and profile_serializer.is_valid(): # Create and save the User with hashed password user = user_serializer.save() user.set_password(user.password) # Hash the password user.save() # Create and link the UserProfileInfo profile = profile_serializer.save(commit=False) profile.user = user profile.registered = True # Preserve your original logic profile.save() # Generate an auth token for the new user (optional but useful) token, created = Token.objects.get_or_create(user=user) # Return cleaned response (exclude password) user_data = user_serializer.data return Response({ "message": "Registration successful", "user": user_data, "profile": profile_serializer.data, "auth_token": token.key }, status=status.HTTP_201_CREATED) else: # Combine errors from both serializers for clarity errors = {**user_serializer.errors, **profile_serializer.errors} return Response(errors, status=status.HTTP_400_BAD_REQUEST)
3. Create the Login API View
You have two solid options here — a fully custom view (to match your original logic closely) or a modified version of DRF's built-in token view:
Option 1: Custom Login View (Matches Your Original Logic)
class LoginAPIView(APIView): def post(self, request): username = request.data.get("username") password = request.data.get("password") # Validate required fields if not username or not password: return Response( {"error": "Please provide both username and password"}, status=status.HTTP_400_BAD_REQUEST ) # Authenticate the user user = authenticate(username=username, password=password) if user: if user.is_active: # Get or create auth token token, created = Token.objects.get_or_create(user=user) return Response({ "message": "Login successful", "user": { "username": user.username, "email": user.email }, "auth_token": token.key }, status=status.HTTP_200_OK) else: return Response( {"error": "Account not active"}, status=status.HTTP_403_FORBIDDEN ) else: return Response( {"error": "Invalid login credentials"}, status=status.HTTP_401_UNAUTHORIZED )
Option 2: Modified DRF Built-In Token View (Shorter, DRF-Native)
If you prefer using DRF's built-in tools, extend ObtainAuthToken to return additional user data:
from rest_framework.authtoken.views import ObtainAuthToken class CustomAuthToken(ObtainAuthToken): def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, context={"request": request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data["user"] token, created = Token.objects.get_or_create(user=user) return Response({ "auth_token": token.key, "user_id": user.pk, "username": user.username, "email": user.email })
4. Configure Your URLs
Update urls.py to point to your new API views:
# urls.py from django.urls import path from .views import RegisterAPIView, LoginAPIView, CustomAuthToken urlpatterns = [ # Registration API path("api/register/", RegisterAPIView.as_view(), name="api_register"), # Login API (use either your custom view or the DRF modified one) path("api/login/", LoginAPIView.as_view(), name="api_login"), # path("api/login/", CustomAuthToken.as_view(), name="api_login"), ]
5. Update Settings.py
Enable token authentication in your project settings:
# settings.py INSTALLED_APPS = [ # ... your existing apps "rest_framework", "rest_framework.authtoken", "your_app_name", # Replace with your actual app name ] REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ "rest_framework.authentication.TokenAuthentication", ], }
6. Test the APIs
You can test these endpoints using tools like Postman, curl, or DRF's built-in browsable API:
- Registration: Send a POST request to
/api/register/with JSON body:{ "username": "testuser", "email": "test@example.com", "password": "testpass123", "phone_no": "1234567890" } - Login: Send a POST request to
/api/login/with JSON body:{ "username": "testuser", "password": "testpass123" }
The response will include an auth token that you can use to authenticate subsequent API requests (add a header Authorization: Token <your-token>).
内容的提问来源于stack exchange,提问作者Ankit0395

