使

使用 Python、Django 和 Django Rest Framework 开发 Restful API 简介 使用 Django Rest Framework 开发 REST API 源代码 奖励

2025-05-25

使用 Python、Django 和 Django Rest Framework 开发 Restful API

介绍

使用 Django Rest Framework 的 REST API

源代码

奖金

介绍

对于想要使用 Python、Django 和 Django Rest Framework 开发 RESTful API 项目的初学者来说,本文是一份权威指南。

  • Django是一个用Python编写的Web框架

  • Python是一种用于通用编程的解释型高级编程语言

  • API或应用程序编程接口是一组规则和机制,一个应用程序或组件通过这些规则和机制与其他应用程序或组件进行交互

  • REST或表述性状态转移是一种软件架构

REST API

正如 Roy Fielding 在一篇论文中所描述的那样,

REST 是一种“架构风格”,它基本上利用了现有的 Web 技术和协议。

简单来说,它是以适合客户端的格式呈现的数据。

因此,RESTful + API 是实现此类架构和约束(例如在 Web 服务中)的常用术语。

以下是来自 GitHub API 的一个GET请求示例

$ curl https://api.github.com/users/joshuadeguzman
Enter fullscreen mode Exit fullscreen mode

您将看到类似如下的输出

{
  "login": "joshuadeguzman",
  "id": 20706361,
  "node_id": "MDQ6VXNlcjIwNzA2MzYx",
  "avatar_url": "https://avatars1.githubusercontent.com/u/20706361?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/joshuadeguzman",
  "html_url": "https://github.com/joshuadeguzman",
  "followers_url": "https://api.github.com/users/joshuadeguzman/followers",
  "following_url": "https://api.github.com/users/joshuadeguzman/following{/other_user}",
  "gists_url": "https://api.github.com/users/joshuadeguzman/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/joshuadeguzman/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/joshuadeguzman/subscriptions",
  "organizations_url": "https://api.github.com/users/joshuadeguzman/orgs",
  "repos_url": "https://api.github.com/users/joshuadeguzman/repos",
  "events_url": "https://api.github.com/users/joshuadeguzman/events{/privacy}",
  "received_events_url": "https://api.github.com/users/joshuadeguzman/received_events",
  "type": "User",
  "site_admin": false,
  "name": "Joshua de Guzman",
  "company": "@freelancer",
  "blog": "https://joshuadeguzman.me",
  "location": "Manila, PH",
  "email": null,
  "hireable": true,
  "bio": "Android Engineer at @freelancer. Building tools for humans.",
  "public_repos": 75,
  "public_gists": 2,
  "followers": 38,
  "following": 10,
  "created_at": "2016-07-28T15:19:54Z",
  "updated_at": "2019-06-16T10:26:39Z"
}
Enter fullscreen mode Exit fullscreen mode

上面显示的是JSON格式的数据集

JSONJavaScript 对象表示法是一种开放标准文件格式,它使用人类可读的文本来传输由属性值对和数组数据类型组成的数据对象。

其他格式包括 XML、INI、CSV 等。但如今,JSON 被广泛使用,因为它的结构直观,无论使用什么编程语言,都可以轻松读取和映射域对象。

Python 和 Django

Python的创始人 Guido van Rossum 认为,Python 是一个

高级编程语言,其核心设计理念是代码的可读性和允许程序员用几行代码表达概念的语法。

Python 使用类似英语的词汇表示法(例如方法、保留关键字和控制流),这使得任何初学者都能轻松上手。它还具有动态类型系统,这意味着它会在运行时验证程序的类型安全性。它还具有自动内存管理功能。

print(5 + 5) # This will result to 10
Enter fullscreen mode Exit fullscreen mode

Django是一个高级 Python Web 框架,它使开发人员能够以简洁、实用的设计按时交付项目。

其旗舰功能包括快速开发的设计、安全和可扩展的产品。

Django 快速概览

Django 将更改传播到数据库模式的方式是通过其迁移模块。

示例User模型

from django.db import models

class User(models.Model):
    first_name = models.CharField(max_length=50)
    middle_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        return self.name
Enter fullscreen mode Exit fullscreen mode

如果您的模型有任何更改,请运行makemigrations

$ python manage.py makemigrations
Enter fullscreen mode Exit fullscreen mode

最后,您可以将数据库与模型和迁移集同步

$ python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

使用 Django Rest Framework 的 REST API

DRF,即 Django REST 框架,是一个强大而灵活的 Web API 构建工具包。它可以帮助开发人员避免自己从头开始构建复杂而可靠的 REST API,从而避免重复造轮子。因为随着项目变得越来越复杂,您很快就会意识到使用 DRF 或其他实用 REST 框架的必要性。

1. 安装和项目设置

创建项目目录

$ mkdir djangoapi
Enter fullscreen mode Exit fullscreen mode

通过pip安装virtualenv

虚拟环境使项目能够在其环境中拥有额外的库或对包进行更改,而不会干扰全局或其他环境的库。

pip是一个用Python编写的用于安装和管理软件包的包管理系统。

$ pip install virtualenv
Enter fullscreen mode Exit fullscreen mode

在项目目录中创建环境文件夹

$ cd djangoapi
$ virtualenv venv
Enter fullscreen mode Exit fullscreen mode

激活环境

$ source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

要撤消对路径的这些更改,只需运行deactivate。有关virtualenv 的更多信息。

安装djangodjangorestframework

$ pip install django
$ pip install djangorestframework
Enter fullscreen mode Exit fullscreen mode

创建django 项目

$ django-admin startproject blog
Enter fullscreen mode Exit fullscreen mode

运行你的项目

$ python manage.py runserver

System check identified no issues (0 silenced).

You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

August 16, 2018 - 09:58:36
Django version 2.1, using settings 'blog.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Enter fullscreen mode Exit fullscreen mode

未应用的迁移指启动 django 项目时包含的默认迁移文件。

要同步这些迁移文件,只需运行migrate

$ python manage.py migrate

Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK
Enter fullscreen mode Exit fullscreen mode

我们项目中的默认数据库当前设置为名为的 SQLite db.sqlite3

创建django 项目的应用程序

$ cd blog
$ python manage.py startapp posts
Enter fullscreen mode Exit fullscreen mode

项目结构应该是这样的

$ find .
./posts
./posts/migrations
./posts/migrations/__init__.py
./posts/models.py
./posts/__init__.py
./posts/apps.py
./posts/admin.py
./posts/tests.py
./posts/views.py
./db.sqlite3
./blog
./blog/__init__.py
./blog/__pycache__
./blog/__pycache__/settings.cpython-36.pyc
./blog/__pycache__/wsgi.cpython-36.pyc
./blog/__pycache__/__init__.cpython-36.pyc
./blog/__pycache__/urls.cpython-36.pyc
./blog/settings.py
./blog/urls.py
./blog/wsgi.py
./manage.py
Enter fullscreen mode Exit fullscreen mode

2. 模型

每个模型实例都是数据信息的可靠来源。通常,每个模型都对应数据库中的一个表。

# djangoapi/blog/posts/models.py
from django.db import models

# Create your models here.

class Post(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    is_featured = models.BooleanField(default=False)

    def __str__(self):
        return self.name
Enter fullscreen mode Exit fullscreen mode

__str__str()内置函数和打印语句调用来计算对象的“非正式”字符串表示。

如果您尝试运行makemigrations,django 将不会看到这些更改。

$ No changes detected
Enter fullscreen mode Exit fullscreen mode

为了解决此问题,请将您的posts应用添加到项目的已安装应用中。

# djangoapi/blog/blog/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'posts' # Add it here
]
Enter fullscreen mode Exit fullscreen mode

继续模型迁移

$ python manage.py makemigrations

Migrations for 'posts':
  posts/migrations/0001_initial.py
    - Create model Post

$ python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, posts, sessions
Running migrations:
  Applying posts.0001_initial... OK

Enter fullscreen mode Exit fullscreen mode

3.序列化

序列化器允许将数据结构或对象状态转换为可以存储或传输并在以后重建的格式。

创建 APIserializers.pyviews.py文件并像这样隔离它们

# posts/api
posts/api/serializers.py
posts/api/views.py

# posts/migrations
posts/migrations/

# posts
posts/admin.py
posts/apps.py
posts/models.py
posts/tests.py
posts/views.py
Enter fullscreen mode Exit fullscreen mode
# posts/api/serializers.py

from ..models import Post
from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('title', 'content', 'is_featured') # if not declared, all fields of the model will be shown
Enter fullscreen mode Exit fullscreen mode

在本教程中,我们使用了有关此内容ModelSerializer的更多内容

4. 视图

视图函数(或简称视图)是一个接受 Web 请求并返回 Web 响应的 Python 函数。

# posts/api/views.py

from ..models import Post
from . import serializers
from rest_framework import generics, status
from rest_framework.response import Response

class PostListView(generics.ListAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer
Enter fullscreen mode Exit fullscreen mode

如上所示,ListAPIView用于只读端点来表示模型实例的集合。

在此代码片段中,我们使用了generics来自的视图方法rest_framework,有关更多信息请参见此

5. URL

在这里,我们设置我们的路线或 URL 路径到我们指定的视图,我们期望每个视图都有特定的响应。

# posts/urls.py

from django.urls import path
from . import views
from .api import views

urlpatterns = [
    path('', views.PostListView.as_view(), name=None)
]
Enter fullscreen mode Exit fullscreen mode

6. 完成设置

确保rest_framework已添加到我们项目的应用程序中。

# djangoapi/blog/blog/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # Add it here
    'posts'
]
Enter fullscreen mode Exit fullscreen mode

7. Django 管理员

由于我们尚未设置POST请求,我们将通过 django 的管理面板填充数据库。

为此,请创建一个admin带有密码的超级用户帐户1234password

$ python manage.py createsuperuser --email admin@example.com --username admin

Password:
Password (again):
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
Enter fullscreen mode Exit fullscreen mode

在管理面板中注册模型。

# posts/admin.py

from django.contrib import admin
from .models import Post

# Register your models here.
admin.site.register(Post)
Enter fullscreen mode Exit fullscreen mode

就这样。访问管理面板并更新posts模型记录。更多信息请参见

8.测试我们的API

$ python manage.py runserver
Enter fullscreen mode Exit fullscreen mode
GET /api/v1/posts/
Enter fullscreen mode Exit fullscreen mode
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "title": "Example Post #1",
        "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "is_featured": false
    },
    {
        "title": "Example Post #2",
        "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "is_featured": true
    }
]
Enter fullscreen mode Exit fullscreen mode

太好了。现在我们该更新视图并完成标准的 CRUD 操作了。

9. 添加更多视图

POST是一种用于在数据库中创建(有时更新)资源的方法。

# posts/api/views.py

from ..models import Post
from . import serializers
from rest_framework import generics, status
from rest_framework.response import Response

class PostCreateView(generics.CreateAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer

    def create(self, request, *args, **kwargs):
        super(PostCreateView, self).create(request, args, kwargs)
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully created",
                    "result": request.data}
        return Response(response)
Enter fullscreen mode Exit fullscreen mode

通常,当我们想要公开数据集列表时,我们会分离List和查看类,同时轻松阻止某个请求或在数据库中为该特定视图创建资源。CreatePOSTList

用例总是因应用程序而异,您可以选择使用ListCreateAPIView甚至ViewSets来组合一组相关视图的逻辑。

可选:由于我们希望以更系统的方式显示数据,因此我们覆盖create方法并映射内联自定义响应处理程序。

添加更多带有方法的视图GET以处理特定的博客文章详细信息。PATCHDELETE

class PostDetailView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Post.objects.all()
    serializer_class = serializers.PostSerializer

    def retrieve(self, request, *args, **kwargs):
        super(PostDetailView, self).retrieve(request, args, kwargs)
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = serializer.data
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully retrieved",
                    "result": data}
        return Response(response)

    def patch(self, request, *args, **kwargs):
        super(PostDetailView, self).patch(request, args, kwargs)
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        data = serializer.data
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully updated",
                    "result": data}
        return Response(response)

    def delete(self, request, *args, **kwargs):
        super(PostDetailView, self).delete(request, args, kwargs)
        response = {"status_code": status.HTTP_200_OK,
                    "message": "Successfully deleted"}
        return Response(response)
Enter fullscreen mode Exit fullscreen mode

10.更新URL

# posts/urls.py

from django.urls import path
from . import views
from .api import views

urlpatterns = [
    path('', views.PostListView.as_view(), name=None),
    path('create/', views.PostCreateView.as_view(), name=None),
    path('<int:pk>/', views.PostDetailView.as_view(), name=None)
]
Enter fullscreen mode Exit fullscreen mode

现在您可以通过Postman、您的应用程序向您的 API 发送请求,或者GET从您的浏览器发出请求,例如:

POST /api/v1/posts/create/
Enter fullscreen mode Exit fullscreen mode
HTTP 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "status_code": 200,
    "message": "Successfully created",
    "result": {
        "csrfmiddlewaretoken": "rnSUN3XOIghnXA0yKghnQgxg0do39xhorYene5ALw3gWGThK5MjG6YjL8VUb7v2h",
        "title": "Creating a resource",
        "content": "Howdy mate!"
    }
}
Enter fullscreen mode Exit fullscreen mode
GET /api/v1/posts/1/
Enter fullscreen mode Exit fullscreen mode
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "status_code": 200,
    "message": "Successfully retrieved",
    "result": {
        "title": "Sample Post",
        "content": "Sample Post Content",
        "is_featured": false
    }
}
Enter fullscreen mode Exit fullscreen mode

就这样!您已经成功使用 DRF 开发 RESTful API 了!干杯!

源代码

可在GitHub上获取

奖金

我将介绍另一篇文章,介绍使用JSON Web 令牌进行 RESTful 身份验证的可测试 RESTful API ,并很快在此处添加链接,敬请关注!

如有疑问或建议,请随时评论或联系

文章来源:https://dev.to/joshuamdeguzman/definitive-guide-developing-restful-apis-using-python-django-and-drf-2h7e
PREV
JWT 基础知识简介 简介 - 什么是 JWT?无状态?这意味着什么?进一步分解 - JWT 的组成部分 它如何保证安全?JWT 的缺点:注销用户/使令牌失效 关于复杂性、漏洞等的说明:其他资源:
NEXT
讨厌与 Josh Puetz 谈判的人的薪资谈判