“`markdown
Django REST Framework (DRF) 入门教程:快速构建 API
Django REST Framework (DRF) 是一个强大而灵活的工具包,用于构建 Web API。它基于 Django,提供了序列化、身份验证、权限控制、限流、版本控制等众多功能,极大地简化了 API 开发过程。本文将带你一步步从零开始,使用 DRF 快速构建一个功能完备的 API。
1. 准备工作
在开始之前,确保你已经安装了以下软件:
- Python: Python 3.7 或更高版本是 DRF 的推荐版本。
- pip: Python 的包管理工具。
- Django: Django 框架本身。
如果你还没有安装 Django,可以使用以下命令安装:
bash
pip install django
2. 创建 Django 项目和应用
首先,创建一个新的 Django 项目:
bash
django-admin startproject tutorial
cd tutorial
然后,创建一个 Django 应用,例如 “snippets”,用于存放我们的 API 代码:
bash
python manage.py startapp snippets
3. 安装 Django REST Framework
使用 pip 安装 DRF:
bash
pip install djangorestframework
4. 配置 Django 项目
在 tutorial/settings.py
文件中进行以下配置:
- 将
'rest_framework'
添加到INSTALLED_APPS
中。
python
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # 添加 DRF
'snippets', # 添加 snippets 应用
]
5. 定义模型 (Model)
在 snippets/models.py
中定义一个简单的 Snippet
模型,用于存储代码片段:
“`python
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted([(item, item) for item in get_all_styles()])
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default=”)
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default=’python’, max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default=’friendly’, max_length=100)
owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
highlighted = models.TextField()
class Meta:
ordering = ['created']
def __str__(self):
return self.title or "Snippet {}".format(self.id)
“`
这个模型包含以下字段:
created
: 创建时间,自动添加。title
: 代码片段的标题。code
: 代码片段的内容。linenos
: 是否显示行号。language
: 编程语言。style
: 代码高亮样式。owner
: 代码片段的拥有者,使用 Django 的User
模型。highlighted
: 代码片段的 HTML 高亮版本。
执行数据库迁移:
bash
python manage.py makemigrations snippets
python manage.py migrate
6. 创建序列化器 (Serializer)
序列化器负责将模型实例转换为 JSON 等数据格式,并将 JSON 数据转换为模型实例。在 snippets/serializers.py
中创建 SnippetSerializer
:
“`python
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
from django.contrib.auth.models import User
class SnippetSerializer(serializers.HyperlinkedModelSerializer): # 使用 HyperlinkedModelSerializer,包含 URL 链接
owner = serializers.ReadOnlyField(source=’owner.username’)
highlight = serializers.HyperlinkedIdentityField(view_name=’snippet-highlight’, format=’html’)
class Meta:
model = Snippet
fields = ['url', 'id', 'highlight', 'owner',
'title', 'code', 'linenos', 'language', 'style']
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(many=True, view_name=’snippet-detail’, read_only=True)
class Meta:
model = User
fields = ['url', 'id', 'username', 'snippets']
“`
SnippetSerializer
用于序列化Snippet
模型。UserSerializer
用于序列化User
模型。HyperlinkedModelSerializer
创建包含 URL 链接的序列化数据,更符合 RESTful API 的规范。ReadOnlyField
表示只读字段,owner
字段从owner.username
获取数据。HyperlinkedIdentityField
创建一个指向特定视图的 URL 链接,这里用于高亮显示代码。HyperlinkedRelatedField
创建一个指向相关模型的 URL 链接,这里用于显示用户的所有代码片段。
7. 创建视图 (View)
视图处理 HTTP 请求,并返回响应。DRF 提供了多种视图类,简化了 API 开发。我们使用 ModelViewSet
和 APIView
来创建视图。在 snippets/views.py
中添加以下代码:
“`python
from rest_framework import generics, permissions, renderers, viewsets
from django.contrib.auth.models import User
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from snippets.permissions import IsOwnerOrReadOnly
@api_view([‘GET’])
def api_root(request, format=None):
return Response({
‘users’: reverse(‘user-list’, request=request, format=format),
‘snippets’: reverse(‘snippet-list’, request=request, format=format)
})
class SnippetViewSet(viewsets.ModelViewSet): # 使用 ModelViewSet
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly]
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class UserViewSet(viewsets.ReadOnlyModelViewSet): # 使用 ReadOnlyModelViewSet
queryset = User.objects.all()
serializer_class = UserSerializer
“`
@api_view
装饰器用于创建基于函数的 API 视图,这里用于根 API 视图。reverse
函数用于生成 URL,便于 API 之间的导航。SnippetViewSet
使用ModelViewSet
,它提供了所有 CRUD 操作的默认实现,包括创建、读取、更新和删除。UserViewSet
使用ReadOnlyModelViewSet
,只提供读取操作。permission_classes
指定了访问权限,IsAuthenticatedOrReadOnly
表示只有认证用户才能创建、更新和删除代码片段,其他用户只能读取。IsOwnerOrReadOnly
是一个自定义权限,只有代码片段的拥有者才能更新和删除它。@action
装饰器创建一个自定义行为highlight
,用于高亮显示代码。perform_create
方法用于在创建代码片段时,自动设置owner
字段为当前用户。
8. 创建自定义权限 (Permission)
创建一个自定义权限,确保只有代码片段的拥有者才能更新和删除它。在 snippets/permissions.py
中添加以下代码:
“`python
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
“””
自定义权限,只允许代码片段的拥有者编辑。
“””
def has_object_permission(self, request, view, obj):
# 读取权限允许任何请求,
# 所以我们总是允许 GET, HEAD or OPTIONS 请求。
if request.method in permissions.SAFE_METHODS:
return True
# 只有代码片段的拥有者才允许写操作。
return obj.owner == request.user
“`
9. 配置 URL 路由
在 snippets/urls.py
中配置 URL 路由:
“`python
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
创建一个路由器并注册我们的视图集。
router = DefaultRouter()
router.register(r’snippets’, views.SnippetViewSet)
router.register(r’users’, views.UserViewSet)
API URL 现在由路由器自动确定。
urlpatterns = [
path(”, include(router.urls)),
path(‘api-auth/’, include(‘rest_framework.urls’, namespace=’rest_framework’)), # 添加登录认证支持
path(”, views.api_root),
]
“`
DefaultRouter
会自动生成 API 的 URL 路由。router.register
用于注册视图集。rest_framework.urls
提供了登录认证支持。
在 tutorial/urls.py
中包含 snippets
应用的 URL:
“`python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(”, include(‘snippets.urls’)), # 包含 snippets 应用的 URL
]
“`
10. 添加代码高亮
在 snippets/models.py
中添加 save
方法,用于生成代码片段的 HTML 高亮版本:
“`python
from django.db import models
from pygments.lexers import get_all_lexers, get_lexer_by_name
from pygments.styles import get_all_styles
from pygments import highlight
from pygments.formatters.html import HtmlFormatter
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted([(item, item) for item in get_all_styles()])
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default=”)
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default=’python’, max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default=’friendly’, max_length=100)
owner = models.ForeignKey('auth.User', related_name='snippets', on_delete=models.CASCADE)
highlighted = models.TextField()
class Meta:
ordering = ['created']
def __str__(self):
return self.title or "Snippet {}".format(self.id)
def save(self, *args, **kwargs):
"""
使用 pygments 库创建一个 HTML 高亮版本的代码片段。
"""
lexer = get_lexer_by_name(self.language)
linenos = 'table' if self.linenos else False
options = {'title': self.title} if self.title else {}
formatter = HtmlFormatter(style=self.style, linenos=linenos,
full=True, **options)
self.highlighted = highlight(self.code, lexer, formatter)
super().save(*args, **kwargs)
“`
11. 创建超级用户
创建一个超级用户,用于登录管理界面:
bash
python manage.py createsuperuser
12. 运行开发服务器
启动 Django 开发服务器:
bash
python manage.py runserver
13. 测试 API
现在,你可以使用浏览器或 API 客户端(例如 Postman)测试 API。
- 访问
http://127.0.0.1:8000/
查看根 API 视图。 - 访问
http://127.0.0.1:8000/snippets/
查看代码片段列表。 - 访问
http://127.0.0.1:8000/users/
查看用户列表。 - 访问
http://127.0.0.1:8000/admin/
登录管理界面,管理代码片段和用户。
14. 添加 API 认证
DRF 提供了多种认证方式,包括基本认证、Session 认证、OAuth 认证等。这里我们使用 Session 认证,它与 Django 的用户认证系统集成在一起。
首先,确保你在 snippets/urls.py
中包含了 rest_framework.urls
:
python
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), # 添加登录认证支持
path('', views.api_root),
]
现在,访问 API 时,DRF 会自动添加登录表单,让你进行认证。
15. 添加 Browsable API
DRF 提供了 Browsable API,它是一个交互式的 API 浏览器,方便开发者测试和调试 API。 它默认启用,无需额外配置。 访问API端点时,如果请求的 Accept
头包含 text/html
(例如,通过浏览器访问), DRF 将返回 Browsable API 界面,而不是 JSON 数据。
总结
本文详细介绍了如何使用 Django REST Framework 快速构建 API。我们从创建 Django 项目和应用开始,然后安装 DRF、定义模型、创建序列化器、创建视图、配置 URL 路由、添加代码高亮和 API 认证。通过这个教程,你应该能够掌握 DRF 的基本概念和使用方法,并能够构建自己的 API。
进阶学习
- 自定义序列化器: 学习如何创建自定义序列化器,处理更复杂的数据结构和业务逻辑。
- 自定义视图: 学习如何创建自定义视图,实现更高级的 API 功能。
- 使用不同的认证方式: 了解 DRF 提供的各种认证方式,并选择适合你的场景的认证方式。
- 使用版本控制: 学习如何使用 DRF 的版本控制功能,管理 API 的不同版本。
- 使用测试框架: 学习如何使用 DRF 的测试框架,编写单元测试和集成测试,保证 API 的质量。
DRF 是一个功能强大的框架,掌握它可以极大地提高 API 开发效率。希望本文能帮助你入门 DRF,并在实际项目中灵活运用。
“`