MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python Django框架中的RESTful API开发

2021-06-143.9k 阅读

1. 什么是 RESTful API

RESTful API 即表述性状态传递(Representational State Transfer)风格的应用程序编程接口。它是一种设计 Web 服务的架构风格,具有以下特点:

  • 资源导向:将网络上的所有事物都抽象为资源(Resource),每个资源都有唯一的标识符(URI)。例如,一个博客系统中,每篇文章就是一个资源,其可能的 URI 为 /articles/1,其中 1 是文章的标识符。
  • 无状态性:客户端与服务器之间的每一次交互都包含完成请求所需的所有信息,服务器不会在多次请求间保存客户端的状态。这使得服务器可以更容易地进行扩展,因为每个请求都是独立处理的。
  • 统一接口:使用标准的 HTTP 方法(如 GET、POST、PUT、DELETE 等)来操作资源。GET 通常用于获取资源,POST 用于创建新资源,PUT 用于更新资源,DELETE 用于删除资源。
  • 分层系统:可以将服务器端架构设计为多层,客户端不需要知道服务器端的具体分层结构,只需要与最外层进行交互。

2. Django 框架基础

Django 是一个高级的 Python Web 框架,它采用了 MTV(Model - Template - View)架构模式:

  • Model(模型):负责与数据库交互,定义数据的结构和行为。例如,在一个博客应用中,文章的模型可能包含标题、内容、作者、发布时间等字段。
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length = 200)
    content = models.TextField()
    author = models.CharField(max_length = 100)
    publish_date = models.DateTimeField(auto_now_add = True)
  • Template(模板):负责处理用户界面的展示,通常使用 Django 自己的模板语言。模板可以包含变量、标签和过滤器,用于动态生成 HTML 页面。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF - 8">
    <title>{{ article.title }}</title>
</head>
<body>
    <h1>{{ article.title }}</h1>
    <p>{{ article.content }}</p>
    <p>Author: {{ article.author }}</p>
    <p>Published: {{ article.publish_date }}</p>
</body>
</html>
  • View(视图):接收用户的请求,调用模型获取数据,选择合适的模板并将数据传递给模板进行渲染,最后将渲染后的结果返回给用户。
from django.shortcuts import render
from.models import Article

def article_detail(request, article_id):
    article = Article.objects.get(id = article_id)
    return render(request, 'article_detail.html', {'article': article})

3. 安装与配置 Django REST framework

Django REST framework 是一个用于在 Django 中构建 RESTful API 的强大工具。

  • 安装:可以使用 pip 进行安装。
pip install djangorestframework
  • 配置:在 Django 项目的 settings.py 文件中,将 rest_framework 添加到 INSTALLED_APPS 列表中。
INSTALLED_APPS = [
   ...
   'rest_framework',
]

此外,还可以对 REST framework 进行一些全局配置,例如设置默认的认证类和权限类。

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.SessionAuthentication',
       'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
       'rest_framework.permissions.IsAuthenticated',
    )
}

4. 创建 Django REST framework 项目

  • 创建 Django 项目:使用 Django 命令行工具创建一个新项目。
django - admin startproject myproject
cd myproject
  • 创建应用:在项目目录下创建一个新的应用,例如 articles
python manage.py startapp articles
  • 定义模型:在 articles/models.py 文件中定义文章模型,与前面基础示例类似。
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length = 200)
    content = models.TextField()
    author = models.CharField(max_length = 100)
    publish_date = models.DateTimeField(auto_now_add = True)
  • 迁移数据库:在定义好模型后,需要迁移数据库,使模型的结构在数据库中生效。
python manage.py makemigrations
python manage.py migrate

5. 创建序列化器

序列化器(Serializer)在 Django REST framework 中起着关键作用,它将模型实例或查询集转换为 JSON、XML 等格式的数据,也可以将接收到的外部数据反序列化为模型实例。

  • 创建序列化器类:在 articles 应用中创建一个 serializers.py 文件,定义文章序列化器。
from rest_framework import serializers
from.models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'

这里使用了 ModelSerializer,它是 Serializer 的一个子类,能够根据模型自动生成序列化器字段。fields = '__all__' 表示包含模型的所有字段。如果只想包含部分字段,可以指定字段列表,例如 fields = ['title', 'author']

6. 创建视图集与路由

  • 视图集(ViewSet):视图集是一种将多个视图逻辑组合在一起的方式,它可以通过不同的方法处理不同的 HTTP 请求。在 articles/views.py 文件中创建文章视图集。
from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

ModelViewSet 提供了默认的 list(获取列表)、retrieve(获取单个)、create(创建)、update(更新)和 destroy(删除)等方法,根据不同的 HTTP 请求自动调用。

  • 路由(Router):在 Django REST framework 中,使用路由器来自动生成 URL 模式。在项目的 urls.py 文件中配置路由。
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from articles.views import ArticleViewSet

router = DefaultRouter()
router.register(r'articles', ArticleViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]

router.register(r'articles', ArticleViewSet) 表示将 ArticleViewSet 注册到 articles 这个 URL 前缀下。这样,就可以通过 /articles/ 访问文章列表,通过 /articles/<pk>/ 访问单个文章(<pk> 是文章的主键)。

7. 处理认证与权限

  • 认证(Authentication):Django REST framework 支持多种认证方式,如会话认证(SessionAuthentication)、令牌认证(TokenAuthentication)等。以令牌认证为例,首先需要生成令牌。
python manage.py drf_create_token

settings.py 文件中配置令牌认证。

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
       'rest_framework.authentication.TokenAuthentication',
    )
}

在客户端请求时,需要在请求头中添加令牌信息,例如:

curl -H "Authorization: Token <token_value>" http://localhost:8000/articles/
  • 权限(Permissions):权限用于控制哪些用户可以对资源进行哪些操作。例如,只有认证用户可以创建文章,所有用户可以读取文章。在 views.py 文件中设置权限。
from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer
from rest_framework.permissions import IsAuthenticated, AllowAny

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    def get_permissions(self):
        if self.action == 'create':
            self.permission_classes = [IsAuthenticated]
        else:
            self.permission_classes = [AllowAny]
        return super().get_permissions()

这里通过 get_permissions 方法根据不同的操作设置不同的权限。

8. 过滤与排序

  • 过滤(Filtering):可以使用 django - filter 库来实现对数据的过滤。首先安装 django - filter
pip install django - filter

settings.py 文件中添加 'django_filters'INSTALLED_APPS

INSTALLED_APPS = [
   ...
    'django_filters',
]

views.py 文件中配置过滤。

from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer
from django_filters.rest_framework import DjangoFilterBackend

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['author']

这样,就可以通过 ?author = <author_name> 的方式在 URL 中过滤文章。

  • 排序(Sorting):可以通过 OrderingFilter 实现排序。在 views.py 文件中添加排序配置。
from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer
from rest_framework.filters import OrderingFilter

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ['publish_date']

客户端可以通过 ?ordering = publish_date?ordering = -publish_date 来对文章按发布时间进行升序或降序排序。

9. 处理复杂关系

在实际应用中,模型之间可能存在复杂的关系,如一对多、多对多关系。假设我们有一个作者模型和文章模型,一个作者可以写多篇文章,这是一对多的关系。

  • 定义模型:在 articles/models.py 文件中定义作者模型和文章模型。
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length = 100)

class Article(models.Model):
    title = models.CharField(max_length = 200)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete = models.CASCADE)
    publish_date = models.DateTimeField(auto_now_add = True)
  • 序列化器处理:在 serializers.py 文件中,需要正确处理这种关系。
from rest_framework import serializers
from.models import Author, Article

class ArticleSerializer(serializers.ModelSerializer):
    author_name = serializers.CharField(source = 'author.name', read_only = True)

    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author_name', 'publish_date']

class AuthorSerializer(serializers.ModelSerializer):
    articles = ArticleSerializer(many = True, read_only = True)

    class Meta:
        model = Author
        fields = ['id', 'name', 'articles']

这里,ArticleSerializer 中通过 source = 'author.name' 创建了一个 author_name 字段来显示作者的名字。AuthorSerializer 中通过 articles = ArticleSerializer(many = True, read_only = True) 来显示作者的所有文章。

10. 测试 RESTful API

可以使用多种工具来测试 RESTful API,如 curl、Postman 等。

  • 使用 curl:获取文章列表。
curl http://localhost:8000/articles/

创建一篇文章(假设已经进行了认证,这里以令牌认证为例)。

curl -X POST -H "Authorization: Token <token_value>" -H "Content - Type: application/json" -d '{"title":"New Article", "content":"This is a new article", "author":"John Doe"}' http://localhost:8000/articles/
  • 使用 Postman:打开 Postman,输入 URL,选择请求方法(如 GET、POST 等),添加请求头(如认证信息),填写请求体(对于 POST 请求),然后发送请求,查看响应结果。

11. 性能优化

在开发 RESTful API 时,性能优化至关重要。

  • 数据库查询优化
    • 减少查询次数:尽量避免在循环中进行数据库查询。例如,如果需要获取多篇文章及其作者信息,不要为每篇文章单独查询作者,而是使用 select_related 方法进行预加载。
articles = Article.objects.select_related('author').all()
- **使用索引**:对经常用于查询条件的字段添加索引。在模型定义中,可以通过 `db_index = True` 来添加索引。
class Article(models.Model):
    title = models.CharField(max_length = 200, db_index = True)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete = models.CASCADE)
    publish_date = models.DateTimeField(auto_now_add = True)
  • 缓存:可以使用 Django 的缓存机制来缓存 API 响应。在 settings.py 文件中配置缓存。
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

在视图中使用缓存。

from django.views.decorators.cache import cache_page
from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    @cache_page(60 * 15) # 缓存15分钟
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)

12. 错误处理与日志记录

  • 错误处理:Django REST framework 提供了默认的错误处理机制,但可以根据项目需求进行自定义。在 settings.py 文件中配置自定义的错误处理函数。
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER':'myproject.utils.custom_exception_handler'
}

myproject/utils.py 文件中定义自定义错误处理函数。

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status

def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)

    if response is None:
        response = Response({
           'status': 'error',
           'message': 'An unexpected error occurred'
        }, status = status.HTTP_500_INTERNAL_SERVER_ERROR)

    return response
  • 日志记录:在 Django 中,可以配置日志记录来记录 API 的运行情况。在 settings.py 文件中配置日志。
LOGGING = {
   'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'api.log',
        },
    },
    'loggers': {
       'myproject': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

在视图中记录日志。

import logging
from rest_framework.viewsets import ModelViewSet
from.models import Article
from.serializers import ArticleSerializer

logger = logging.getLogger('myproject')

class ArticleViewSet(ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    def create(self, request, *args, **kwargs):
        try:
            return super().create(request, *args, **kwargs)
        except Exception as e:
            logger.error(f"Error creating article: {str(e)}")
            raise

通过以上步骤,我们可以在 Django 框架中全面地开发出功能丰富、性能良好且安全的 RESTful API。在实际项目中,还需要根据具体需求进行更多的定制和优化。