DjangoRESTFrameworkAPI开发:从零开始完整教程
Django REST Framework API 开发:从零开始完整教程
Django REST Framework (DRF) 是一个强大且灵活的工具包,用于构建 Web API。它基于 Django,提供了丰富的功能和简便的开发流程,使开发者能够快速高效地构建 RESTful API。本教程将带领你从零开始,一步步学习如何使用 DRF 开发 API,涵盖从环境搭建到高级特性的各个方面。
1. 环境准备
在开始之前,我们需要确保开发环境已准备就绪。这包括安装 Python、Django 和 DRF。
1.1 安装 Python
Django 和 DRF 都是基于 Python 的,所以首先需要安装 Python。建议使用 Python 3.8 或更高版本。你可以从 Python 官网下载并安装适合你操作系统的版本。
安装完成后,可以通过在终端或命令行中输入以下命令来验证安装是否成功:
bash
python --version
如果看到 Python 版本号,说明安装成功。
1.2 创建虚拟环境
强烈建议在虚拟环境中进行项目开发,以隔离项目依赖,避免不同项目之间的冲突。可以使用 venv
模块创建虚拟环境:
bash
python3 -m venv .venv
这将在当前目录下创建一个名为 .venv
的虚拟环境。
1.3 激活虚拟环境
在开始安装依赖之前,需要激活虚拟环境:
- macOS/Linux:
bash
source .venv/bin/activate
- Windows:
bash
.venv\Scripts\activate
激活虚拟环境后,你的终端提示符前会显示虚拟环境的名称(例如 (.venv)
)。
1.4 安装 Django 和 Django REST Framework
在激活的虚拟环境中,使用 pip
安装 Django 和 DRF:
bash
pip install django djangorestframework
你还可以安装一些常用的扩展包,例如:
markdown
:支持 Markdown 格式的文档django-filter
:提供过滤功能
bash
pip install markdown django-filter
2. 创建 Django 项目和应用
2.1 创建 Django 项目
使用 django-admin
命令创建一个新的 Django 项目:
bash
django-admin startproject myproject .
将 myproject
替换为你想要的项目名称。.
表示在当前目录创建项目,这样可以避免多余的目录层级。
2.2 创建 Django 应用
Django 项目由一个或多个应用组成。使用 manage.py
文件创建一个新的应用:
bash
python manage.py startapp myapp
将 myapp
替换为你想要的应用名称。这将在项目目录下创建一个名为 myapp
的目录,其中包含应用的基本文件结构。
2.3 配置项目
接下来,需要对项目进行一些基本配置。
2.3.1 settings.py
打开 myproject/settings.py
文件,进行以下配置:
- 添加应用到
INSTALLED_APPS
:
将新创建的应用和 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',
'myapp', # 你的应用名称
]
- 配置
REST_FRAMEWORK
(可选):
你可以在 settings.py
中添加 REST_FRAMEWORK
配置项,自定义 DRF 的行为。例如,设置默认的渲染器、解析器、认证方式等。这里先使用默认配置,后续会根据需要进行调整。
2.3.2 urls.py
打开 myproject/urls.py
文件,添加应用的 URL 路由:
```python
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapp.urls')), # 添加应用的 URL 路由
]
```
这会将 /api/
开头的请求路由到 myapp
应用的 URL 配置。
2.4 创建应用 URL 文件
在 myapp
目录下创建 urls.py
文件,用于定义应用的 URL 路由:
```python
from django.urls import path
from . import views
urlpatterns = [
# 在这里添加应用的 URL 路由
]
```
3. 构建数据模型
数据模型是 API 的基础,它定义了 API 操作的数据结构。在 myapp/models.py
文件中定义你的数据模型。
3.1 定义模型
例如,我们创建一个简单的 Book
模型,包含书名、作者和出版日期:
```python
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
publication_date = models.DateField()
def __str__(self):
return self.title
```
3.2 数据迁移
定义好模型后,需要进行数据迁移,将模型同步到数据库中。
首先,创建迁移文件:
bash
python manage.py makemigrations
然后,执行迁移:
bash
python manage.py migrate
这些命令会在数据库中创建对应的表。
4. 创建序列化器
序列化器负责将模型实例转换为 JSON 等数据格式,以及将接收到的数据反序列化为模型实例。在 myapp
目录下创建 serializers.py
文件。
4.1 定义序列化器
为 Book
模型创建一个序列化器:
```python
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = 'all' # 或者指定需要的字段,例如:['id', 'title', 'author', 'publication_date']
```
这个序列化器会根据 Book
模型的字段自动生成序列化字段。
5. 创建视图
视图负责处理 API 请求,并返回响应。在 myapp/views.py
文件中定义视图。
5.1 基于函数的视图
我们可以先使用基于函数的视图来快速入门:
```python
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer
@api_view(['GET', 'POST'])
def book_list(request):
"""
列出所有书籍,或创建一本新书。
"""
if request.method == 'GET':
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'PUT', 'DELETE'])
def book_detail(request, pk):
"""
检索、更新或删除一本书籍。
"""
try:
book = Book.objects.get(pk=pk)
except Book.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = BookSerializer(book)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = BookSerializer(book, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
```
这里定义了两个视图函数:
book_list
:处理/api/books/
的 GET 和 POST 请求,分别用于获取所有书籍列表和创建新书。book_detail
:处理/api/books/<pk>/
的 GET、PUT 和 DELETE 请求,分别用于获取、更新和删除指定 ID 的书籍。
5.2 基于类的视图
虽然基于函数的视图简单易懂,但 DRF 更推荐使用基于类的视图,因为它们提供了更好的代码组织和重用性。
下面我们将上述基于函数的视图改写成基于类的视图:
```python
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookList(generics.ListCreateAPIView):
"""
列出所有书籍,或创建一本新书。
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetail(generics.RetrieveUpdateDestroyAPIView):
"""
检索、更新或删除一本书籍。
"""
queryset = Book.objects.all()
serializer_class = BookSerializer
```
这里使用了 DRF 提供的通用视图类:
ListCreateAPIView
:用于处理列表和创建操作。RetrieveUpdateDestroyAPIView
:用于处理检索、更新和删除操作。
这些通用视图类已经实现了常用的逻辑,我们只需要指定 queryset
和 serializer_class
即可。
5.3 其他通用视图类
除了上述两个通用视图类,DRF 还提供了其他常用的通用视图类:
CreateAPIView
:仅用于创建。ListAPIView
:仅用于列表。RetrieveAPIView
:仅用于检索。DestroyAPIView
:仅用于删除。UpdateAPIView
:仅用于更新。RetrieveUpdateAPIView
:用于检索和更新。
你可以根据需要选择合适的通用视图类。
6. 配置 URL
在 myapp/urls.py
文件中配置 URL 路由,将 URL 映射到视图:
```python
from django.urls import path
from . import views
urlpatterns = [
path('books/', views.BookList.as_view()),
path('books/
]
```
7. 测试 API
现在,我们可以启动开发服务器并测试 API 了。
7.1 启动开发服务器
bash
python manage.py runserver
这将启动 Django 开发服务器,默认监听 http://127.0.0.1:8000/
。
7.2 使用浏览器或 Postman 测试
你可以使用浏览器或 Postman 等工具来测试 API。
-
浏览器:
访问
http://127.0.0.1:8000/api/books/
,你将看到书籍列表的 JSON 数据。由于我们使用了ListCreateAPIView
, DRF还会自动生成一个可以用来提交POST请求的表单。
* Postman:你可以使用 Postman 发送 GET、POST、PUT、DELETE 等请求到不同的 API 端点,并查看响应结果。
例如:
- GET
http://127.0.0.1:8000/api/books/
: 获取所有书籍列表。 - POST
http://127.0.0.1:8000/api/books/
: 创建新书,需要在请求体中提供书籍数据。 - GET
http://127.0.0.1:8000/api/books/1/
: 获取 ID 为 1 的书籍信息。 - PUT
http://127.0.0.1:8000/api/books/1/
: 更新 ID 为 1 的书籍信息,需要在请求体中提供更新后的数据。 - DELETE
http://127.0.0.1:8000/api/books/1/
: 删除 ID 为 1 的书籍。
8. 进阶功能
至此,我们已经构建了一个基本的 RESTful API。接下来,我们将介绍一些 DRF 的进阶功能,帮助你构建更强大、更完善的 API。
8.1 认证 (Authentication)
认证用于验证用户的身份。DRF 提供了多种认证方式,例如:
- 基本认证 (BasicAuthentication): 使用用户名和密码进行认证。
- 会话认证 (SessionAuthentication): 使用 Django 的会话系统进行认证。
- 令牌认证 (TokenAuthentication): 使用令牌进行认证,通常用于 API 客户端。
- JWT 认证 (JSON Web Token): 一种流行的令牌认证方式。
8.1.1 配置认证方式
在 settings.py
文件中配置 REST_FRAMEWORK
:
python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
这将启用基本认证和会话认证。
8.1.2 添加Token认证
要使用 Token 认证,需要先在INSTALLED_APPS
中添加 rest_framework.authtoken
:
python
INSTALLED_APPS = [
# ...
'rest_framework.authtoken',
# ...
]
然后执行数据迁移:
bash
python manage.py migrate
这将创建用于存储令牌的数据库表。
接着在REST_FRAMEWORK
中添加:
python
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication', #新增Token认证
]
}
8.1.3 为用户生成Token
可以使用Django Admin后台为用户生成Token,或者通过代码生成:
```python
from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
user = User.objects.get(username='your_username') # 替换为你的用户名
token = Token.objects.create(user=user)
print(token.key)
```
8.1.4 在请求中使用Token
在请求头中添加 Authorization
字段,值为 Token 你的令牌
:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
8.1.5 保护视图
你可以在视图类中添加 authentication_classes
属性,指定需要使用的认证方式:
```python
from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication
from rest_framework.permissions import IsAuthenticated
class BookList(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [SessionAuthentication, BasicAuthentication, TokenAuthentication]
permission_classes = [IsAuthenticated]
```
permission_classes
设置为 IsAuthenticated
表示只有通过认证的用户才能访问该视图。
8.2 权限 (Permissions)
权限用于控制用户对资源的访问权限。DRF 提供了多种权限类,例如:
- AllowAny: 允许所有用户访问。
- IsAuthenticated: 只允许认证用户访问。
- IsAdminUser: 只允许管理员用户访问。
- IsAuthenticatedOrReadOnly: 认证用户可以读写,匿名用户只能读取。
8.2.1 配置权限
你可以在 settings.py
中配置全局的权限类:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
也可以在视图类中单独配置:
```python
from rest_framework.permissions import IsAuthenticated, AllowAny
class BookList(generics.ListCreateAPIView):
# ...
permission_classes = [IsAuthenticated] # 只有认证用户才能访问
# or
# permission_classes = [AllowAny] # 允许所有用户访问
# or
# permission_classes = [IsAuthenticatedOrReadOnly] # 认证用户可读写,匿名用户只读
```
8.3 限流 (Throttling)
限流用于限制 API 的访问频率,防止恶意攻击或滥用。DRF 提供了多种限流方式,例如:
- AnonRateThrottle: 限制匿名用户的访问频率。
- UserRateThrottle: 限制认证用户的访问频率。
- ScopedRateThrottle: 根据不同的视图或操作设置不同的限流策略。
8.3.1 配置限流
在 settings.py
中配置 REST_FRAMEWORK
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
这将限制匿名用户每天最多访问 100 次,认证用户每天最多访问 1000 次。
你也可以在视图类中单独配置:
```python
from rest_framework.throttling import UserRateThrottle
class BookList(generics.ListCreateAPIView):
# ...
throttle_classes = [UserRateThrottle]
throttle_scope = 'books' # 设置限流作用域
```
然后在 settings.py
中配置 ScopedRateThrottle
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.ScopedRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'books': '50/day', # 针对 books 作用域的限流策略
}
}
8.4 过滤 (Filtering)
过滤允许用户根据特定条件筛选数据。DRF 提供了强大的过滤功能。
8.4.1 使用 django-filter
首先,确保已安装 django-filter
:
bash
pip install django-filter
然后,在 settings.py
中将 django_filters
添加到 INSTALLED_APPS
:
python
INSTALLED_APPS = [
# ...
'django_filters',
# ...
]
并在 REST_FRAMEWORK
中添加 DjangoFilterBackend
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend'
],
}
8.4.2 在视图中配置过滤
在视图类中添加 filterset_fields
属性,指定可以过滤的字段:
```python
from django_filters.rest_framework import DjangoFilterBackend
class BookList(generics.ListCreateAPIView):
# ...
filter_backends = [DjangoFilterBackend]
filterset_fields = ['title', 'author'] # 允许按书名和作者过滤
```
现在,你可以通过 URL 参数进行过滤了:
http://127.0.0.1:8000/api/books/?title=Django
:过滤出书名为 "Django" 的书籍。http://127.0.0.1:8000/api/books/?author=John
:过滤出作者为 "John" 的书籍。http://127.0.0.1:8000/api/books/?title=Django&author=John
:同时按书名和作者过滤。
8.4.3 自定义过滤器
django-filter
还支持创建自定义过滤器。
8.5 分页 (Pagination)
当 API 返回大量数据时,分页可以将数据分成多个页面,提高性能和用户体验。
8.5.1 配置分页
在 settings.py
中配置 REST_FRAMEWORK
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10 # 每页显示 10 条数据
}
这将启用分页功能,并设置每页显示 10 条数据。
8.5.2 分页响应
启用分页后,API 的响应会包含分页信息:
json
{
"count": 123,
"next": "http://api.example.org/accounts/?page=5",
"previous": "http://api.example.org/accounts/?page=3",
"results": [
{…},
{…},
…
]
}
count
:总数据量。next
:下一页的 URL。previous
:上一页的 URL。results
:当前页的数据。
8.6 版本控制 (Versioning)
版本控制允许你同时维护 API 的多个版本,方便进行升级和维护。DRF 提供了多种版本控制方式,例如:
- URL 路径版本控制: 在 URL 中包含版本号,例如
/api/v1/books/
。 - 查询参数版本控制: 通过查询参数指定版本号,例如
/api/books/?version=1
。 - 请求头版本控制: 在请求头中指定版本号。
8.6.1 配置版本控制
在 settings.py
中配置 REST_FRAMEWORK
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'ALLOWED_VERSIONS': ['v1', 'v2'], # 允许的版本号
'VERSION_PARAM': 'version' # 版本参数的名称
}
这将启用 URL 路径版本控制。
8.6.2 在 URL 中指定版本号
在 urls.py
中使用 namespace
指定版本号:
```python
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(('myapp.urls', 'myapp'), namespace='v1')),
path('api/v2/', include(('myapp.urls', 'myapp'), namespace='v2')),
]
```
然后在 myapp/urls.py
中添加版本相关的视图:
```python
from django.urls import path
from . import views
app_name = 'myapp' # 添加 app_name
urlpatterns = [
# v1版本的视图
path('books/', views.BookList.as_view(), name='book-list'),
path('books/
# 可以添加v2版本的视图,例如:
# path('v2/books/', views.BookListV2.as_view(), name='book-list-v2'),
]
```
现在,你可以通过不同的 URL 访问不同版本的 API:
/api/v1/books/
:访问 v1 版本的书籍列表。/api/v2/books/
:访问 v2 版本的书籍列表。
8.7 文档 (Documentation)
良好的 API 文档可以帮助开发者更好地理解和使用 API。DRF 可以自动生成交互式的 API 文档。
8.7.1 使用 CoreAPI
CoreAPI 是一个文档生成工具,可以与 DRF 集成。
首先,安装 coreapi
和 pyyaml
:
bash
pip install coreapi pyyaml
然后,在 settings.py
中将 coreapi
添加到 INSTALLED_APPS
:
python
INSTALLED_APPS = [
# ...
'rest_framework_swagger',
# ...
]
并在 REST_FRAMEWORK
中添加 SchemaGenerator
:
python
REST_FRAMEWORK = {
# ...
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
}
8.7.2 使用 Swagger
Swagger 是一种流行的 API 文档工具,可以与 DRF 集成。
首先,安装 django-rest-swagger
:
bash
pip install django-rest-swagger
然后,在 settings.py
中将 rest_framework_swagger
添加到 INSTALLED_APPS
:
python
INSTALLED_APPS = [
# ...
'rest_framework_swagger',
# ...
]
8.7.3 配置 URL
在 myproject/urls.py
中添加 schema 视图的 URL:
```python
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Your API",
default_version='v1',
description="Your API description",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="[email protected]"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=[permissions.AllowAny],
)
urlpatterns = [
# ...
path('swagger
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
# ...
]
```
8.7.4 访问文档
现在,你可以访问以下 URL 查看 API 文档:
/swagger/
:查看 Swagger UI 文档。/redoc/
:查看 ReDoc 文档。
这些文档是根据你的代码自动生成的,包含了 API 的所有端点、参数、请求体、响应体等信息。
9. 总结
本教程详细介绍了如何使用 Django REST Framework 从零开始构建 RESTful API,涵盖了环境准备、模型定义、序列化器、视图、URL 配置、测试、认证、权限、限流、过滤、分页、版本控制和文档等方面的内容。希望本教程能帮助你快速掌握 DRF 的核心概念和常用功能,并构建出强大、高效、易用的 Web API。
当然,DRF 还有更多高级特性和用法等待你去探索,例如自定义渲染器、解析器、认证方式、权限类、限流策略等。你可以参考 DRF 的官方文档深入学习:https://www.django-rest-framework.org/
希望你能在 API 开发的道路上越走越远,构建出更多优秀的 API 产品!