Django REST框架创建REST API

Django REST框架(DRF Django REST framework)是一个强大而灵活的工具包,用于构建Web API。在本教程中,我们将学习如何在短短15分钟内使用Django REST框架构建CRUD API。

什么是Django?

Django是一个免费的、开源的、基于Python的Web框架,它遵循模型-视图-模板(MVT Model-View-Template)架构模式。它减少了网络开发的麻烦,因此你可以专注于编写你的应用程序,而不是重新发明车轮。

什么是REST API?

REST API是系统暴露有用功能和数据的一种流行方式。REST是表示状态转移的意思,它可以由一个或多个资源组成,这些资源可以通过给定的URL访问,并以各种格式返回,如JSON、图片、HTML等。

Django REST框架

Django REST框架(DRF)是一个强大而灵活的工具包,用于构建Web APIs。它的主要优点是序列化更加容易。

Django REST框架是基于Django的基于类的视图,所以如果你熟悉Django,它是一个很好的选择。它采用了基于类的视图、表单、模型验证器、QuerySet等实现。

环境准备

# pip install django
# pip install django_rest_framework
$ django-admin startproject todo
$ django-admin startapp todo_api
$ python manage.py migrate

在todo/todo/settings.py文件内的INSTALLED_APPS中加入rest_framework和todo。

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'todo_api'
]

在todo/todo_api中创建serializers.py和urls.py文件,并按照下面的目录结构配置添加新的文件。

├── todo
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
├── db.sqlite3
├── manage.py
└── todo_api
    ├── admin.py
    ├── serializers.py
    ├── __init__.py
    ├── models.py
    ├── urls.py
    └── views.py

请确保在你的 urls.py 文件中包含 rest_framework 和 URLs,如下所示。

# todo/todo/urls.py : Main urls.py
from django.contrib import admin
from django.urls import path, include
from todo_api import urls as todo_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('todos/', include(todo_urls)),
]

# todo/todo_api/urls.py : API urls.py
from django.conf.urls import url
from django.urls import path, include
from .views import (
    TodoListApiView,
)

urlpatterns = [
    path('api', TodoListApiView.as_view()),
]

# todo/todo_api/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework import permissions
from .models import Todo
from .serializers import TodoSerializer

class TodoListApiView(APIView):
    # add permission to check if user is authenticated
    permission_classes = [permissions.IsAuthenticated]

    # 1. List all
    def get(self, request, *args, **kwargs):
        '''
        List all the todo items for given requested user
        '''
        todos = Todo.objects.filter(user = request.user.id)
        serializer = TodoSerializer(todos, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    # 2. Create
    def post(self, request, *args, **kwargs):
        '''
        Create the Todo with given todo data
        '''
        data = {
            'task': request.data.get('task'), 
            'completed': request.data.get('completed'), 
            'user': request.user.id
        }
        serializer = TodoSerializer(data=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)


# todo/todo_api/models.py
from django.db import models
from django.contrib.auth.models import User

class Todo(models.Model):
    task = models.CharField(max_length = 180)
    timestamp = models.DateTimeField(auto_now_add = True, auto_now = False, blank = True)
    completed = models.BooleanField(default = False, blank = True)
    updated = models.DateTimeField(auto_now = True, blank = True)
    user = models.ForeignKey(User, on_delete = models.CASCADE, blank = True, null = True)

    def __str__(self):
        return self.task


# todo/todo_api/models.py
from django.db import models
from django.conf import settings

class Todo(models.Model):
    task = models.CharField(max_length = 180)
    timestamp = models.DateTimeField(auto_now_add = True, auto_now = False, blank = True)
    completed = models.BooleanField(default = False, blank = True)
    updated = models.DateTimeField(auto_now = True, blank = True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE, blank = True, null = True)

    def __str__(self):
        return self.task

# todo/todo_api/serializers.py
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Todo
        fields = ["task", "completed", "timestamp", "updated", "user"]

$ python manage.py makemigrations
$ python manage.py migrate

接下来,创建一个超级用户。我们稍后会再来讨论这个问题。


python manage.py createsuperuser

完整代码下载:django-REST-demo.zip: (访问密码: 2274) 无需注册,点击普通下载就好。

RESTful结构:GET、POST、PUT和DELETE方法

在RESTful API中,端点用GET、POST、PUT和DELETE等HTTP方法定义结构和用法。

参考资料

演示

#   curl POST
$ curl  -d '{"task":"hello","completed":false}'  -H "Content-Type: application/json" http://localhost:8008/todos/api
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   162  100   128  100    34   9922   2635 --:--:-- --:--:-- --:--:-- 13500{"task":"hello","completed":false,"timestamp":"2023-02-14T07:21:42.196527Z","updated":"2023-02-14T07:21:42.196527Z","user":null}

#   curl GET
$ curl http://localhost:8008/todos/api
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   416  100   416    0     0  96924      0 --:--:-- --:--:-- --:--:--  135k[{"id":1,"task":"New Task","completed":false,"timestamp":"2023-02-14T07:01:18.488881Z","updated":"2023-02-14T07:01:18.488881Z","user":null},{"id":2,"task":"my_login4","completed":false,"timestamp":"2023-02-14T07:08:24.215626Z","updated":"2023-02-14T07:08:24.215626Z","user":null},{"id":3,"task":"hello","completed":false,"timestamp":"2023-02-14T07:21:42.196527Z","updated":"2023-02-14T07:21:42.196527Z","user":null}]

$ curl http://localhost:8008/todos/api/3/
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   135  100   135    0     0  25153      0 --:--:-- --:--:-- --:--:-- 27000{"id":3,"task":"hello","completed":false,"timestamp":"2023-02-14T07:21:42.196527Z","updated":"2023-02-14T07:21:42.196527Z","user":null}


上面content部分可以输入如下内容

{
    "task": "New Task",
    "completed": false
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容