You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django Rest Framework中用ApiView不使用Serializer实现学生注册登录API的CRUD?

用DRF的ApiView实现学生注册、登录及CRUD(不使用Serializer)

1. 定义学生模型

先在models.py中创建包含核心字段的Student模型,同时封装密码加密与验证方法:

from django.db import models
from django.contrib.auth.hashers import make_password, check_password

class Student(models.Model):
    username = models.CharField(max_length=50, unique=True)
    email = models.EmailField(unique=True)
    password = models.CharField(max_length=255)
    full_name = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def set_password(self, raw_password):
        self.password = make_password(raw_password)
    
    def check_password(self, raw_password):
        return check_password(raw_password, self.password)

2. 实现注册API(POST)

在views.py中编写注册视图,手动解析请求数据、验证字段唯一性并创建学生对象:

from django.http import JsonResponse
from rest_framework.views import APIView
from .models import Student
import json

class StudentRegisterView(APIView):
    def post(self, request):
        # 解析请求JSON
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({"error": "无效的JSON数据"}, status=400)
        
        # 检查必填字段
        required_fields = ['username', 'email', 'password', 'full_name']
        for field in required_fields:
            if field not in data:
                return JsonResponse({"error": f"缺少必填字段: {field}"}, status=400)
        
        # 验证用户名/邮箱唯一性
        if Student.objects.filter(username=data['username']).exists():
            return JsonResponse({"error": "用户名已被占用"}, status=400)
        if Student.objects.filter(email=data['email']).exists():
            return JsonResponse({"error": "邮箱已注册"}, status=400)
        
        # 创建学生并加密密码
        student = Student(
            username=data['username'],
            email=data['email'],
            full_name=data['full_name']
        )
        student.set_password(data['password'])
        student.save()
        
        # 返回创建后的学生信息(隐藏密码)
        return JsonResponse({
            "id": student.id,
            "username": student.username,
            "email": student.email,
            "full_name": student.full_name,
            "created_at": student.created_at.strftime("%Y-%m-%d %H:%M:%S")
        }, status=201)

3. 实现登录API(POST)

编写登录视图,验证用户名与密码的正确性:

class StudentLoginView(APIView):
    def post(self, request):
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({"error": "无效的JSON数据"}, status=400)
        
        username = data.get('username')
        password = data.get('password')
        
        if not username or not password:
            return JsonResponse({"error": "用户名和密码为必填项"}, status=400)
        
        try:
            student = Student.objects.get(username=username)
        except Student.DoesNotExist:
            return JsonResponse({"error": "无效的登录凭证"}, status=401)
        
        if not student.check_password(password):
            return JsonResponse({"error": "无效的登录凭证"}, status=401)
        
        # 返回登录成功信息与学生数据
        return JsonResponse({
            "message": "登录成功",
            "student": {
                "id": student.id,
                "username": student.username,
                "email": student.email,
                "full_name": student.full_name
            }
        }, status=200)

4. 实现学生CRUD接口

4.1 学生列表接口(GET)

获取所有学生的基础信息:

class StudentListView(APIView):
    def get(self, request):
        students = Student.objects.all()
        student_list = []
        for student in students:
            student_list.append({
                "id": student.id,
                "username": student.username,
                "email": student.email,
                "full_name": student.full_name,
                "created_at": student.created_at.strftime("%Y-%m-%d %H:%M:%S"),
                "updated_at": student.updated_at.strftime("%Y-%m-%d %H:%M:%S")
            })
        return JsonResponse({"students": student_list}, status=200)

4.2 学生详情/更新/删除接口(GET/PUT/DELETE)

根据学生ID处理单个学生的查询、更新与删除操作:

class StudentDetailView(APIView):
    def get_object(self, pk):
        try:
            return Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return None
    
    def get(self, request, pk):
        student = self.get_object(pk)
        if not student:
            return JsonResponse({"error": "学生不存在"}, status=404)
        
        return JsonResponse({
            "id": student.id,
            "username": student.username,
            "email": student.email,
            "full_name": student.full_name,
            "created_at": student.created_at.strftime("%Y-%m-%d %H:%M:%S"),
            "updated_at": student.updated_at.strftime("%Y-%m-%d %H:%M:%S")
        }, status=200)
    
    def put(self, request, pk):
        student = self.get_object(pk)
        if not student:
            return JsonResponse({"error": "学生不存在"}, status=404)
        
        try:
            data = json.loads(request.body)
        except json.JSONDecodeError:
            return JsonResponse({"error": "无效的JSON数据"}, status=400)
        
        # 更新字段逻辑
        if 'email' in data:
            if Student.objects.filter(email=data['email']).exclude(pk=pk).exists():
                return JsonResponse({"error": "邮箱已被注册"}, status=400)
            student.email = data['email']
        
        if 'full_name' in data:
            student.full_name = data['full_name']
        
        if 'password' in data:
            student.set_password(data['password'])
        
        student.save()
        
        return JsonResponse({
            "id": student.id,
            "username": student.username,
            "email": student.email,
            "full_name": student.full_name,
            "updated_at": student.updated_at.strftime("%Y-%m-%d %H:%M:%S")
        }, status=200)
    
    def delete(self, request, pk):
        student = self.get_object(pk)
        if not student:
            return JsonResponse({"error": "学生不存在"}, status=404)
        
        student.delete()
        return JsonResponse({"message": "学生已成功删除"}, status=204)

5. 配置URL路由

在urls.py中完成视图与URL的映射:

from django.urls import path
from .views import (
    StudentRegisterView,
    StudentLoginView,
    StudentListView,
    StudentDetailView
)

urlpatterns = [
    path('register/', StudentRegisterView.as_view(), name='student-register'),
    path('login/', StudentLoginView.as_view(), name='student-login'),
    path('students/', StudentListView.as_view(), name='student-list'),
    path('students/<int:pk>/', StudentDetailView.as_view(), name='student-detail'),
]

注意事项

  • 手动验证数据时需覆盖必填字段检查、唯一性校验,避免数据库抛出异常
  • 必须使用Django内置的哈希方法处理密码,禁止明文存储
  • 若需权限控制,可在视图中添加permission_classes,比如限制仅登录用户修改自身信息
  • 登录接口如需持久化会话,可结合Django Session或生成JWT Token(需额外依赖djangorestframework-simplejwt)

内容的提问来源于stack exchange,提问作者Khushal Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:35:19