SuperAPI AI Directory

django

General & other

View repository

Updated 10-16 06:51

About this skill

Django REST Framework Backend Development Standards

Trigger Conditions

  • Develop Django projects
  • Implement REST APIs
  • Use DRF ViewSets and Serializers
  • Implement JWT authentication
  • Implement permission control

Part 1: Technology Stack

Layer Selection Description
Runtime Environment Python 3.11+ Type Annotation Enhancement
Web Framework Django 4.2+ Full-stack framework, built-in ORM
REST API Django REST Framework (DRF) ViewSet, Serializer, Authentication
Database MySQL 8.x (mysqlclient) InnoDB Engine
Cache Redis 7.x (django-redis) Distributed Cache
Authentication PyJWT + DRF Authentication Token issuance/verification
API Documentation drf-spectacular OpenAPI 3.0 auto-generation

Part 2: Directory Structure

project/
├── apps/                           # 应用模块
│   ├── system/                     # 系统管理(Django App)
│   │   ├── users/                  # 用户管理(models, serializers, views, urls, filters)
│   │   ├── roles/                  # 角色管理
│   │   ├── menus/                  # 菜单管理
│   │   ├── dept/                   # 部门管理
│   │   ├── dicts/                  # 字典管理
│   │   ├── configs/                # 系统配置
│   │   ├── notices/                # 通知公告
│   │   ├── logs/                   # 日志管理
│   │   └── utils/                  # decorators, exception_handler, rate_limit
│   ├── auth/                       # 认证模块
│   │   ├── views.py, serializers.py, urls.py
│   │   ├── utils/                  # jwt_authentication, redis_token_authentication
│   │   └── models/                 # user_session, user_social
│   ├── codegen/                    # 代码生成器(models, views, urls, templates/)
│   ├── file/                       # 文件管理
│   └── message/                    # 消息模块(SSE)
├── core/                           # 公共模块
│   ├── response.py                 # 统一响应 + 分页
│   ├── viewsets.py                 # ViewSet 基类
│   ├── serializers.py              # Serializer 基类
│   ├── exceptions/                 # BusinessException + 全局处理器
│   ├── permissions/                # 接口权限 + 数据权限
│   └── middleware/                 # rate_limit, request_context
├── config/                         # 项目配置
│   ├── settings/{base,dev,prod}.py
│   ├── urls.py                     # 根路由
│   └── env.py
├── sql/mysql/youlai_admin_django.sql
├── manage.py
└── requirements.txt

Design Principles:

  • core/ is shared public infrastructure, used by all Apps, and does not depend on business Apps
  • apps/ In each App, submodules are divided by entity (user/role/menu), and each submodule contains models/serializers/views/urls/filters
  • ViewSet + Serializer is the standard pattern; complex business logic is extracted to services.py

Part 3: Naming Conventions

3.1 File Naming

Type Convention Example
Module Directory lowercase plural users/, roles/, menus/
Model models.py apps/system/users/models.py
Serializer serializers.py Same as above
View views.py Same as above
Route urls.py Same as above
Filter filters.py Same as above

3.2 Class Naming

Type Convention Example
Model PascalCase, Sys prefix SysUser, SysRole, SysMenu
Serializer Feature + Serializer UserSerializer, UserFormSerializer
ViewSet Feature + ViewSet UserViewSet
Filter Feature + Filter UserFilter

3.3 Method Naming

Action DRF built-in methods Custom action
Query list list() page()
Query detail retrieve() —
Create create() —
Update update() —
Delete destroy() —
Batch delete — batch()
Dropdown options — options()

3.4 Variable Naming

Type Convention Example
Variable snake_case user_list
Constant UPPER_SNAKE_CASE MAX_PAGE_SIZE
Private method _ prefix _parse_date()
Boolean value is_/has_ prefix is_deleted, has_permission

Part 4: RESTful API Standards

4.1 Standard CRUD Paths

Operation Method Path
Paginated list GET /api/v1/users/page/
Detail GET /api/v1/users/{id}/
Create POST /api/v1/users/
Update PUT /api/v1/users/{id}/
Delete DELETE /api/v1/users/{id}/
Batch delete DELETE /api/v1/users/batch/
Dropdown options GET /api/v1/users/options/

4.2 ViewSet Template

@extend_schema(tags=["用户管理"])
class UserViewSet(ModelViewSet):
    queryset = SysUser.objects.all()
    serializer_class = UserSerializer
    filterset_class = UserFilter
    permission_classes = [HasPermission]

    @extend_schema(summary="用户分页列表")
    @action(detail=False, methods=["get"])
    def page(self, request):
        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        return page_result(self.get_serializer(page, many=True).data, self.paginator.count)

    @extend_schema(summary="新增用户")
    def create(self, request, *args, **kwargs):
        serializer = UserFormSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.save()
        return success_result({"id": user.id})

    @extend_schema(summary="更新用户")
    def update(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = UserFormSerializer(instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return success_result()

    @extend_schema(summary="删除用户")
    def destroy(self, request, *args, **kwargs):
        self.get_object().delete()
        return success_result()

Part 5: Response Format and Exception Handling

5.1 Unified Response

def success_result(data=None, msg="操作成功"):
    return Response({"code": 200, "msg": msg, "data": data})

def page_result(list_data, total, msg="操作成功"):
    return Response({"code": 200, "msg": msg, "data": {"list": list_data, "total": total}})

def error_result(code=400, msg="操作失败", data=None):
    return Response({"code": code, "msg": msg, "data": data})

5.2 Business Exceptions

from rest_framework.exceptions import APIException

class BusinessException(APIException):
    status_code = 200  # 统一 200,业务码在 body 中
    default_detail = "业务异常"
    default_code = 400

    def __init__(self, detail=None, code=400):
        self.detail = detail or self.default_detail
        self.code = code

5.3 Global Exception Handling

class GlobalExceptionHandler:
    def __call__(self, exc, context):
        if isinstance(exc, BusinessException):
            return error_result(code=exc.code, msg=str(exc.detail))
        if isinstance(exc, APIException):
            return error_result(code=exc.status_code, msg=str(exc.detail))
        return error_result(code=500, msg="系统异常")

Part 6: Model Standards

class BaseModel(models.Model):
    id = models.BigAutoField(primary_key=True)
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    is_deleted = models.BooleanField(default=False, verbose_name="是否删除")

    class Meta:
        abstract = True

    def delete(self, *args, **kwargs):
        """逻辑删除。"""
        self.is_deleted = True
        self.save()

class SysUser(BaseModel):
    username = models.CharField(max_length=50, unique=True, verbose_name="用户名")
    password = models.CharField(max_length=100, verbose_name="密码")
    nickname = models.CharField(max_length=50, verbose_name="昵称")
    mobile = models.CharField(max_length=20, blank=True, verbose_name="手机号")
    status = models.SmallIntegerField(default=1, verbose_name="状态")
    dept = models.ForeignKey("SysDept", on_delete=models.SET_NULL, null=True, verbose_name="部门")

    class Meta:
        db_table = "sys_user"

Part 7: Serializer Standards

class UserSerializer(serializers.ModelSerializer):
    """用户 VO 序列化器。"""
    class Meta:
        model = SysUser
        fields = ["id", "username", "nickname", "mobile", "email", "status", "create_time"]

class UserFormSerializer(serializers.ModelSerializer):
    """用户表单序列化器。"""
    class Meta:
        model = SysUser
        fields = ["id", "username", "password", "nickname", "mobile", "email", "status", "dept"]

    def validate_username(self, value):
        if SysUser.objects.filter(username=value, is_deleted=False).exclude(
            id=self.instance.id if self.instance else None).exists():
            raise serializers.ValidationError("用户名已存在")
        return value

    def create(self, validated_data):
        validated_data["password"] = bcrypt.hashpw(validated_data["password"])
        return super().create(validated_data)

Part 8: Authentication Standards

8.1 JWT Authentication

class JWTAuthentication(BaseAuthentication):
    def authenticate(self, request):
        token = request.META.get("HTTP_AUTHORIZATION", "").replace("Bearer ", "")
        if not token:
            return None
        try:
            payload = jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"])
        except jwt.ExpiredSignatureError:
            raise AuthenticationFailed("Token 已过期")
        except jwt.InvalidTokenError:
            raise AuthenticationFailed("无效 Token")
        user = SysUser.objects.get(id=payload["sub"], is_deleted=False)
        return (user, token)

8.2 Permission Classes

class HasPermission(BasePermission):
    def has_permission(self, request, view):
        required = getattr(view, "required_permissions", [])
        if not required:
            return True
        return any(p in request.user.permissions for p in required)

Part 9: Comment Standards

  • docstring first: All public classes and methods must have docstrings
  • Chinese first: Keep proper nouns in English, explain in Chinese
class UserViewSet(ModelViewSet):
    """用户管理 ViewSet。

    提供用户分页查询、增删改查、下拉选项等接口。
    所有接口(除 options 外)需认证。
    """

    @action(detail=False, methods=["get"])
    def page(self, request):
        """用户分页列表。

        Args:
            request: DRF Request 对象,Query 参数含 pageNum/pageSize/keywords/status。

        Returns:
            Response: {"code": 200, "data": {"list": [...], "total": int}}
        """
        ...

Part 10: Code Quality Checklist

  • Follow RESTful API path conventions
  • Use a unified response format (success_result / page_result)
  • ViewSet + Serializer standard pattern
  • Permission checks use HasPermission
  • Models inherit BaseModel
  • Use soft delete (is_deleted)
  • Add @extend_schema annotation to API
  • Serializer validates immutable operations
  • Complex queries use Filter class
  • Public methods have docstrings

Common Anti-patterns

Anti-pattern Correct Practice
return Response(data) Return directly Use success_result(data) unified wrapper
try/except Exception: pass Throw BusinessException or log
User.objects.get(id=id) No exception handling Catch DoesNotExist → throw BusinessException
Write complex business logic in the View Extract to Model Manager or services.py
request.data["key"] No validation Go through Serializer is_valid(raise_exception=True)