django-dev-ninja
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDjango Ninja API Development
Django Ninja API开发
Opinionated Django Ninja patterns with single-endpoint-per-file organization.
采用“每个文件对应一个端点”组织方式的Django Ninja约定式开发模式。
Core Principles
核心原则
- One endpoint = one file - Each endpoint lives in its own file
- Logical grouping - Endpoints grouped in subpackages by domain
- Router per group - Each group has its own router
- Schemas in separate package - Pydantic models in
schemas/ - Services for logic - Business logic in services, not endpoints
- 一个端点对应一个文件 - 每个端点单独存放在一个文件中
- 按领域逻辑分组 - 端点按业务领域划分子包进行分组
- 每组一个路由 - 每个业务组拥有独立的Router
- Schema独立分包 - Pydantic模型存放在目录下
schemas/ - 业务逻辑抽离至服务层 - 业务逻辑实现于服务层,而非端点中
API Structure
API结构
myapp/
├── api/
│ ├── __init__.py # Main NinjaAPI instance
│ ├── users/
│ │ ├── __init__.py # Router: users_router
│ │ ├── list.py # GET /users/
│ │ ├── detail.py # GET /users/{id}
│ │ ├── create.py # POST /users/
│ │ ├── update.py # PUT /users/{id}
│ │ └── delete.py # DELETE /users/{id}
│ ├── products/
│ │ ├── __init__.py
│ │ ├── list.py
│ │ ├── detail.py
│ │ └── search.py
│ └── auth/
│ ├── __init__.py
│ ├── login.py
│ ├── logout.py
│ └── refresh.py
└── schemas/
├── __init__.py
├── user.py # UserIn, UserOut, UserPatch
├── product.py
└── common.py # Pagination, errorsmyapp/
├── api/
│ ├── __init__.py # 主NinjaAPI实例
│ ├── users/
│ │ ├── __init__.py # 路由:users_router
│ │ ├── list.py # GET /users/
│ │ ├── detail.py # GET /users/{id}
│ │ ├── create.py # POST /users/
│ │ ├── update.py # PUT /users/{id}
│ │ └── delete.py # DELETE /users/{id}
│ ├── products/
│ │ ├── __init__.py
│ │ ├── list.py
│ │ ├── detail.py
│ │ └── search.py
│ └── auth/
│ ├── __init__.py
│ ├── login.py
│ ├── logout.py
│ └── refresh.py
└── schemas/
├── __init__.py
├── user.py # UserIn, UserOut, UserPatch
├── product.py
└── common.py # 分页、错误处理SchemaMain API Setup
主API配置
In :
api/__init__.pypython
from ninja import NinjaAPI
from ninja.security import HttpBearer
from .users import router as users_router
from .products import router as products_router
from .auth import router as auth_router
class AuthBearer(HttpBearer):
def authenticate(self, request, token):
# Token validation logic
from ..services.auth import AuthService
return AuthService.validate_token(token)
api = NinjaAPI(
title="My API",
version="1.0.0",
description="API documentation",
auth=AuthBearer(),
)在中:
api/__init__.pypython
from ninja import NinjaAPI
from ninja.security import HttpBearer
from .users import router as users_router
from .products import router as products_router
from .auth import router as auth_router
class AuthBearer(HttpBearer):
def authenticate(self, request, token):
# Token验证逻辑
from ..services.auth import AuthService
return AuthService.validate_token(token)
api = NinjaAPI(
title="My API",
version="1.0.0",
description="API文档",
auth=AuthBearer(),
)Register routers
注册路由
api.add_router("/users", users_router, tags=["Users"])
api.add_router("/products", products_router, tags=["Products"])
api.add_router("/auth", auth_router, tags=["Authentication"], auth=None)
undefinedapi.add_router("/users", users_router, tags=["Users"])
api.add_router("/products", products_router, tags=["Products"])
api.add_router("/auth", auth_router, tags=["Authentication"], auth=None)
undefinedRouter Setup
路由配置
Each group has a router in :
__init__.pypython
undefined每个业务组在中定义路由:
__init__.pypython
undefinedapi/users/init.py
api/users/init.py
from ninja import Router
from .list import router as list_router
from .detail import router as detail_router
from .create import router as create_router
from .update import router as update_router
from .delete import router as delete_router
router = Router()
from ninja import Router
from .list import router as list_router
from .detail import router as detail_router
from .create import router as create_router
from .update import router as update_router
from .delete import router as delete_router
router = Router()
Merge endpoint routers
合并端点路由
router.add_router("", list_router)
router.add_router("", detail_router)
router.add_router("", create_router)
router.add_router("", update_router)
router.add_router("", delete_router)
undefinedrouter.add_router("", list_router)
router.add_router("", detail_router)
router.add_router("", create_router)
router.add_router("", update_router)
router.add_router("", delete_router)
undefinedEndpoint File Template
端点文件模板
Each endpoint in its own file:
python
undefined每个端点单独存放在一个文件中:
python
undefinedapi/users/create.py
api/users/create.py
from ninja import Router
from django.http import HttpRequest
from ...schemas.user import UserIn, UserOut
from ...services.user import UserService
router = Router()
@router.post("/", response={201: UserOut})
def create_user(request: HttpRequest, payload: UserIn) -> UserOut:
"""Create a new user."""
user = UserService.create(payload)
return user
undefinedfrom ninja import Router
from django.http import HttpRequest
from ...schemas.user import UserIn, UserOut
from ...services.user import UserService
router = Router()
@router.post("/", response={201: UserOut})
def create_user(request: HttpRequest, payload: UserIn) -> UserOut:
"""创建新用户。"""
user = UserService.create(payload)
return user
undefinedSchema Organization
Schema组织
Pydantic schemas in package:
schemas/python
undefinedPydantic Schema存放在包中:
schemas/python
undefinedschemas/user.py
schemas/user.py
from uuid import UUID
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field
class UserBase(BaseModel):
"""Shared user fields."""
email: EmailStr
name: str = Field(max_length=255)
class UserIn(UserBase):
"""Input schema for creating users."""
password: str = Field(min_length=8)
class UserPatch(BaseModel):
"""Partial update schema."""
email: EmailStr | None = None
name: str | None = Field(None, max_length=255)
class UserOut(UserBase):
"""Output schema for users."""
id: UUID
is_active: bool
created_at: datetime
class Config:
from_attributes = Trueundefinedfrom uuid import UUID
from datetime import datetime
from pydantic import BaseModel, EmailStr, Field
class UserBase(BaseModel):
"""用户共享字段。"""
email: EmailStr
name: str = Field(max_length=255)
class UserIn(UserBase):
"""创建用户的输入Schema。"""
password: str = Field(min_length=8)
class UserPatch(BaseModel):
"""部分更新Schema。"""
email: EmailStr | None = None
name: str | None = Field(None, max_length=255)
class UserOut(UserBase):
"""用户输出Schema。"""
id: UUID
is_active: bool
created_at: datetime
class Config:
from_attributes = TrueundefinedCommon Patterns
通用模式
Pagination
分页
python
undefinedpython
undefinedschemas/common.py
schemas/common.py
from typing import Generic, TypeVar, List
from pydantic import BaseModel
T = TypeVar("T")
class PaginatedResponse(BaseModel, Generic[T]):
items: List[T]
total: int
page: int
per_page: int
pages: int
```pythonfrom typing import Generic, TypeVar, List
from pydantic import BaseModel
T = TypeVar("T")
class PaginatedResponse(BaseModel, Generic[T]):
items: List[T]
total: int
page: int
per_page: int
pages: int
```pythonapi/users/list.py
api/users/list.py
from ninja import Router, Query
from ...schemas.user import UserOut
from ...schemas.common import PaginatedResponse
router = Router()
@router.get("/", response=PaginatedResponse[UserOut])
def list_users(
request,
page: int = Query(1, ge=1),
per_page: int = Query(20, ge=1, le=100),
):
"""List users with pagination."""
from ...services.user import UserService
return UserService.list_paginated(page, per_page)
undefinedfrom ninja import Router, Query
from ...schemas.user import UserOut
from ...schemas.common import PaginatedResponse
router = Router()
@router.get("/", response=PaginatedResponse[UserOut])
def list_users(
request,
page: int = Query(1, ge=1),
per_page: int = Query(20, ge=1, le=100),
):
"""分页列出用户。"""
from ...services.user import UserService
return UserService.list_paginated(page, per_page)
undefinedError Handling
错误处理
python
undefinedpython
undefinedschemas/common.py
schemas/common.py
class ErrorResponse(BaseModel):
detail: str
code: str | None = None
class ValidationErrorResponse(BaseModel):
detail: list[dict]
```pythonclass ErrorResponse(BaseModel):
detail: str
code: str | None = None
class ValidationErrorResponse(BaseModel):
detail: list[dict]
```pythonapi/users/detail.py
api/users/detail.py
from ninja import Router
from django.http import Http404
from ...schemas.user import UserOut
from ...schemas.common import ErrorResponse
router = Router()
@router.get("/{user_id}", response={200: UserOut, 404: ErrorResponse})
def get_user(request, user_id: UUID):
"""Get user by ID."""
from ...services.user import UserService
user = UserService.get_by_id(user_id)
if not user:
return 404, {"detail": "User not found", "code": "USER_NOT_FOUND"}
return userundefinedfrom ninja import Router
from django.http import Http404
from ...schemas.user import UserOut
from ...schemas.common import ErrorResponse
router = Router()
@router.get("/{user_id}", response={200: UserOut, 404: ErrorResponse})
def get_user(request, user_id: UUID):
"""根据ID获取用户。"""
from ...services.user import UserService
user = UserService.get_by_id(user_id)
if not user:
return 404, {"detail": "用户未找到", "code": "USER_NOT_FOUND"}
return userundefinedFile Upload
文件上传
python
undefinedpython
undefinedapi/files/upload.py
api/files/upload.py
from ninja import Router, File, UploadedFile
from ...schemas.file import FileOut
router = Router()
@router.post("/upload", response=FileOut)
def upload_file(request, file: UploadedFile = File(...)):
"""Upload a file."""
from ...services.file import FileService
return FileService.save(file)
undefinedfrom ninja import Router, File, UploadedFile
from ...schemas.file import FileOut
router = Router()
@router.post("/upload", response=FileOut)
def upload_file(request, file: UploadedFile = File(...)):
"""上传文件。"""
from ...services.file import FileService
return FileService.save(file)
undefinedURL Configuration
URL配置
Register API in :
urls.pypython
undefined在中注册API:
urls.pypython
undefinedconfig/urls.py
config/urls.py
from django.urls import path
from apps.myapp.api import api
urlpatterns = [
path("api/", api.urls),
]
undefinedfrom django.urls import path
from apps.myapp.api import api
urlpatterns = [
path("api/", api.urls),
]
undefinedAuthentication Patterns
认证模式
See for detailed authentication patterns including:
references/endpoints.md- JWT authentication
- API key authentication
- Session authentication
- Permission decorators
查看获取详细的认证模式,包括:
references/endpoints.md- JWT认证
- API密钥认证
- Session认证
- 权限装饰器
Additional Resources
额外资源
Reference Files
参考文件
- - Detailed endpoint patterns, authentication, permissions
references/endpoints.md - - Router organization, versioning, OpenAPI customization
references/routers.md
- - 详细的端点模式、认证、权限说明
references/endpoints.md - - 路由组织、版本控制、OpenAPI自定义说明
references/routers.md
Related Skills
相关技能
- django-dev - Core Django patterns and model organization
- django-dev-test - Testing API endpoints with pytest
- django-dev - 核心Django模式与模型组织
- django-dev-test - 使用pytest测试API端点