本文目录导读:
我来详细介绍如何使用Django REST Framework (DRF) 快速生成完整的API接口。
基础环境搭建
安装依赖
pip install django pip install djangorestframework pip install django-filter # 过滤支持 pip install django-cors-headers # CORS支持
创建项目和APP
django-admin startproject myproject cd myproject python manage.py startapp api
配置settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'django_filters',
'corsheaders',
'api', # 你的APP
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 放在最前面
# ... 其他中间件
]
# REST Framework配置
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
],
}
# CORS配置
CORS_ALLOW_ALL_ORIGINS = True # 开发环境使用
快速创建模型(Model)
models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Article(models.Model):
STATUS_CHOICES = [
('draft', 'Draft'),
('published', 'Published'),
('archived', 'Archived'),
]
= models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='articles')
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='articles')
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.title
创建序列化器(Serializer)
serializers.py
from rest_framework import serializers
from .models import Category, Article
from django.contrib.auth.models import User
class CategorySerializer(serializers.ModelSerializer):
article_count = serializers.IntegerField(read_only=True)
class Meta:
model = Category
fields = ['id', 'name', 'description', 'created_at', 'article_count']
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email']
class ArticleSerializer(serializers.ModelSerializer):
author_detail = UserSerializer(source='author', read_only=True)
category_name = serializers.CharField(source='category.name', read_only=True)
class Meta:
model = Article
fields = [
'id', 'title', 'content', 'author', 'author_detail',
'category', 'category_name', 'status',
'created_at', 'updated_at'
]
read_only_fields = ['author', 'created_at', 'updated_at']
def validate_title(self, value):
if len(value) < 10:
raise serializers.ValidationError("标题至少10个字符")
return value
创建视图(View)
views.py - 使用ViewSet(最快速的方式)
from rest_framework import viewsets, permissions, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from .models import Category, Article
from .serializers import CategorySerializer, ArticleSerializer
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['name']
search_fields = ['name', 'description']
@action(detail=True, methods=['get'])
def articles(self, request, pk=None):
category = self.get_object()
articles = Article.objects.filter(category=category)
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['status', 'category', 'author']
search_fields = ['title', 'content']
ordering_fields = ['created_at', 'updated_at', 'title']
ordering = ['-created_at']
def perform_create(self, serializer):
serializer.save(author=self.request.user)
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
article = self.get_object()
article.status = 'published'
article.save()
return Response({'status': 'published'})
@action(detail=False, methods=['get'])
def my_articles(self, request):
articles = Article.objects.filter(author=request.user)
page = self.paginate_queryset(articles)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(articles, many=True)
return Response(serializer.data)
配置路由(URL)
urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import CategoryViewSet, ArticleViewSet
router = DefaultRouter()
router.register(r'categories', CategoryViewSet)
router.register(r'articles', ArticleViewSet)
urlpatterns = [
path('api/', include(router.urls)),
path('api-auth/', include('rest_framework.urls')), # DRF登录界面
]
高级特性集成
添加认证和权限
# permissions.py
from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.author == request.user
使用mixins组合不同API
from rest_framework import mixins, generics
class CreateListCategoryView(mixins.CreateModelMixin,
mixins.ListModelMixin,
generics.GenericAPIView):
queryset = Category.objects.all()
serializer_class = CategorySerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
添加API版本控制
# urls.py
from django.urls import path, include
urlpatterns = [
path('api/v1/', include('api.urls_v1')),
path('api/v2/', include('api.urls_v2')),
]
运行和测试
迁移数据库
python manage.py makemigrations python manage.py migrate
创建超级用户
python manage.py createsuperuser
运行服务器
python manage.py runserver
访问API
- 浏览API: http://localhost:8000/api/
- 文章列表: GET http://localhost:8000/api/articles/
- 创建文章: POST http://localhost:8000/api/articles/
- 文章详情: GET http://localhost:8000/api/articles/1/
- 更新文章: PUT http://localhost:8000/api/articles/1/
- 删除文章: DELETE http://localhost:8000/api/articles/1/
- 过滤文章: GET http://localhost:8000/api/articles/?status=published
- 搜索文章: GET http://localhost:8000/api/articles/?search=django
- 排序文章: GET http://localhost:8000/api/articles/?ordering=-created_at
自定义API行为
自定义序列化器
class ArticleDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
depth = 1 # 自动嵌套关联对象
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'status', 'created_at']
在不同action使用不同序列化器
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
def get_serializer_class(self):
if self.action == 'list':
return ArticleListSerializer
elif self.action == 'retrieve':
return ArticleDetailSerializer
return ArticleSerializer
这样你就拥有了一个功能完整的REST API接口,支持CRUD操作、过滤、搜索、排序、分页、认证等功能。