设计一个RESTful API来与SQLite数据库交互
在本章中,我们将为HTTP请求创建Django API视图,并将讨论Django和Django REST框架如何处理每个HTTP请求。
- 创建Django视图
- 将URL路由到Django视图和函数
- 启动Django的开发服务器
- 使用命令行工具进行HTTP请求
- 用Postman做HTTP请求
创建Django视图
在前面的章节中,你已经看到了如何创建一个模型和它的序列化器。现在,让我们来看看如何处理HTTP请求并提供HTTP响应。在这里,我们将创建Django视图来处理HTTP请求。在收到一个HTTP请求时,Django会创建一个HttpRequest实例,并将其作为第一个参数传递给视图函数。这个实例包含有HTTP动词的元数据信息,如GET、POST或PUT。视图函数检查该值并根据HTTP动词执行代码。这里的代码使用@csrf_exempt装饰器来设置一个CSRF(跨站请求伪造)cookie。这使得测试代码更加容易,它并没有描绘出一个可用于生产的网络服务。让我们进入代码实现。
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from rest_framework import status
from taskmanagement.models import TaskManagement
from taskmanagement.serializers import TaskMngSerializer
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
@csrf_exempt
def task_list(request):
if request.method == 'GET':
task = TaskManagement.objects.all()
task_serializer = TaskMngSerializer(task, many=True)
return JSONResponse(task_serializer.data)
elif request.method == 'POST':
task_data = JSONParser().parse(request)
task_serializer = TaskMngSerializer(data=task_data)
if task_serializer.is_valid():
task_serializer.save()
return JSONResponse(task_serializer.data, \
status=status.HTTP_201_CREATED)
return JSONResponse(task_serializer.errors, \
status = status.HTTP_400_BAD_REQUEST)
@csrf_exempt
def task_detail(request, pk):
try:
task = TaskManagement.objects.get(pk=pk)
except TaskManagement.DoesNotExist:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
task_serializer = TaskMngSerializer(task)
return JSONResponse(task_serializer.data)
elif request.method == 'PUT':
task_data = JSONParser().parse(request)
task_serializer = TaskMngSerializer(task, data=task_data)
if task_serializer.is_valid():
task_serializer.save()
return JSONResponse(task_serializer.data)
return JSONResponse(task_serializer.errors, \
status=status.HTTP_400_BAD_REQUESTS)
elif request.method == 'DELETE':
task.delete()
return HttpResponse(status=status.HTTP_204_NO_CONTENT)
让我们评估一下这段代码。这里我们有两个函数。
- task_list()
- task_detail()
注意:以后我们将为我们的RESTFul网络服务添加安全和节流规则。而且,我们还需要删除重复的代码。现在,上述代码对于理解基本事物的运作是必要的。
task_list()
task_list()函数能够处理两个HTTP动词 – GET和POST。
如果动词是GET,代码会检索所有的任务管理实例。
如果 request.method == ‘GET’:
task = TaskManagement.objects.all()
task_serializer = TaskMngSerializer(task, many=True)
return JSONResponse(task_serializer.data)
- 它使用TaskManagement.objects.all()方法检索所有任务。
- 使用TaskMngSerializer(task, many=True)将任务序列化。
- 由TaskMngSerializer生成的数据被传递给JSONResponse ,并且
- 返回建立的JSONResponse。
注意: TaskMngSerializer(task, many=True)中的many=True参数指定多个实例必须被序列化。
如果动词是POST,代码会创建一个新的任务。在这里,新任务在HTTP请求的主体中以JSON数据的形式提供。
elif request.method == ‘POST’:
task_data = JSONParser().parse(request)
task_serializer = TaskMngSerializer(data=task_data)
if task_serializer.is_valid():
task_serializer.save()
return JSONResponse(task_serializer.data, \
status=status.HTTP_201_CREATED)
return JSONResponse(task_serializer.errors, \
status = status.HTTP_400_BAD_REQUEST)
- 使用JSONParser来解析该请求。
- 使用TaskMngSerializer,将解析的数据序列化。
- 如果数据是有效的,它将被保存在数据库中,并且
- 返回构建的JSONResponse(包含数据和HTTP_201_CREATED状态)。
task_detail()
task_detail()函数能够处理三种HTTP动词–GET、PUT和DELETE。在这里,该函数接收主键作为参数,并对具有相同键的特定实例进行相应的操作。
如果动词是GET,那么代码会根据键来检索一个任务。如果动词是PUT,那么代码会更新实例并将其保存到数据库中。如果动词是DELETE,那么代码会根据pk值将实例从数据库中删除。
JSONResponse()
除了解释的两个函数外,代码中还有一个名为JSONResponse的类。
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs[‘content_type’] = ‘application/json’
super(JSONResponse, self).__init__(content, **kwargs)
它将数据渲染成JSON格式,并将返回的字节字符串保存在content局部变量中。
将URL路由到Django视图和函数
现在,有必要将URLs路由到视图。你需要在任务管理文件夹(restapi\taskmanagement)中创建一个新的Python文件,名为urls.py,并添加以下代码。
from django.conf.urls import url
from taskmanagement import views
urlpatterns = [
url(r'^taskmanagement/',views.task_list),
url(r'^taskmanagement/(?P<pk>[0-9]+)', views.task_detail),
]
基于匹配的正则表达式,URL被路由到相应的视图。接下来,我们必须替换restapi文件夹中urls.py文件的代码(restapi\restapi\urls.py)。目前,它有根URL的配置。用下面的代码更新urls.py文件。
from django.conf.urls import url, include
urlpatterns = [
url(r'^',include('taskmanagement.urls')),
]
启动Django的开发服务器
激活虚拟环境后,你可以运行以下命令来启动服务器。
python manage.py runserver
分享下面的截图。
Development server
使用命令行工具进行HTTP请求
让我们利用我们在第一章中安装的命令行工具。
HTTP GET请求
HTTP GET请求是用来从数据库中检索任务的细节。我们可以使用GET请求来检索一个任务集合或一个单一任务。
检索所有元素
下面的curl命令检索了一个任务的集合。
curl -X GET localhost:8000/taskmanagement/
输出:
在执行命令时,Django会创建一个HttpRequest实例,并将其作为第一个参数传递给视图函数。Django将该URL路由到相应的视图函数中。这里的视图有两个方法,task_list和task_detail。让我们来看看URL模式,它是在taskmanagement\urls.py文件中配置的
urlpatterns = [
url(r’^taskmanagement/’,views.task_list),
url(r’^taskmanagement/(?P<pk>[0-9]+)’, views.task_detail),
]
这里的URL(localhost:8000/taskmanagement/)与views.task_list的URL模式相匹配。_task_list方法__被执行并检查HTTP动词。由于我们请求的HTTP动词是GET,它检索了所有的任务。
让我们运行命令,通过结合-i和-X选项来检索所有的任务。这里的好处是,它显示了HTTP响应头、状态、内容-类型等。
curl -iX GET localhost:8000/taskmanagement/
输出:
到目前为止,我们已经执行了cURL命令。现在,我们将看看HTTPie实用程序命令,以编写和发送HTTP请求。为此,我们需要访问安装在虚拟环境中的HTTPie工具提示。激活虚拟环境后,运行下面的命令。
http :8000/taskmanagement/
该命令发送了请求。GET http://localhost:8000/taskmanagement/。
输出:
HTTPie实用GET请求 – 检索所有任务
检索单一元素
现在你已经熟悉了检索任务集合的命令。接下来,让我们了解如何根据任务ID检索任务。在这里,我们将把任务ID与URL一起传递。由于URL有一个参数,Django将URL路由到task_detail函数。让我们来执行这些命令。
HTTPie实用程序命令来检索一个单一的任务。
http :8000/taskmanagement/2
上述命令发送了请求。GET http://localhost:8000/taskmanagement/2。
输出:
使用HTTPie工具检索单个元素
相等的curl命令如下。
curl -iX GET localhost:8000/taskmanagement/2
输出:
让我们尝试检索一个不在数据库中的元素。
http :8000/taskmanagement/5
输出如下
HTTP/1.1 404 Not Found
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Fri, 30 Oct 2020 14:32:46 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.7.5
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
HTTP POST请求
我们使用POST请求来创建一个任务。用HTTPUtilityPie命令来创建一个新的请求,如下所示。
http POST :8000/taskmanagement/ task_name=”Document XYZ” task_desc=”Document Description” category=”Writing” priority=”Low” created_date=”2020-10-30 00:00:00.000000+00:00″ deadline=”2020-11-03 00:00:00.000000+00:00″ status=”Pending” payment_done=false
这里的URL请求(http POST :8000/taskmanagement/)与正则表达式(taskmanagement/$)匹配。因此,它调用了函数task_list,,POST动词满足了执行任务创建代码的条件。
输出:
使用HTTPUtilityPie的POST请求
让我们用curl命令创建另一个实例。用于POST请求的curl命令如下
curl -iX POST -H “Content-Type: application/json” -d “{\”task_name\”:\”Task 01\”, \”task_desc\”:\”Desc 01\”, \”category\”:\”Writing\”, \”priority\”:\”Medium\”, \”created_date\”:\”2020-10-27 13:02:20.890678\”, \”deadline\”:\”2020-10-29 00:00:00.000000+00:00\”, \”status\”:\”Completed\”, \”payment_done\”: \”true\”}” localhost:8000/taskmanagement/
输出:
使用curl的POST请求
在这里,创建一个新任务所需的数据被指定在-d之后,使用-H “Content-Type: application/json”表示数据是JSON格式。
{
“task_name”:”Task 01″, “task_desc”:”Desc 01″, “category”:”Writing”, “priority”:”Medium”, “created_date”:”2020-10-27 13:02:20.890678″, “deadline”:”2020-10-29 00:00:00.000000+00:00″, “status”:”Completed”, “payment_done”: “true”
}
HTTP PUT请求
我们利用PUT请求来更新一个现有的任务。在这里,我们把需要更新的任务的ID和URL一起传递给对方。由于URL有一个参数,Django将URL实例发送到视图中的task_detail函数。并且,执行持有PUT动词条件的代码。
更新任务的HTTPie实用命令。
http PUT :8000/taskmanagement/1 task_name=”Swap two elements” task_desc=”Write a Python program to swap two elements in a list” category=”Writing” priority=”Medium” created_date=”2020-10-27 13:02:20.890678″ deadline=”2020-10-29 00:00:00.000000+00:00″ status=”Completed” payment_done=true
输出:
PUT
相等的CURL命令如下
curl -iX PUT -H “Content-Type: application/json” -d “{\”task_name\”:\”Swap two elements\”, \”task_desc\”:\”Write a Python program to swap two elements in a list\”, \”category\”:\”Writing\”, \”priority\”:\”Medium\”, \”created_date\”:\”2020-10-27 13:02:20.890678\”, \”deadline\”:\”2020-10-29 00:00:00.000000+00:00\”, \”status\”:\”Completed\”, \”payment_done\”: \”true\”}” localhost:8000/taskmanagement/1
HTTP DELETE请求
HTTP DELETE请求是用来从数据库中删除一个特定的任务。让我们来看看HTTPie实用命令。
http DELETE :8000/taskmanagement/4
输出:
Delete Request
相等的curl命令如下。
curl -iX DELETE localhost:8000/taskmanagement/4
用Postman做HTTP请求
到目前为止,我们利用了命令行工具来编写和发送HTTP请求。现在,我们将使用Postman。Postman REST客户端是一个图形用户界面(GUI)工具,它可以方便地编写和发送HTTP请求到Django开发服务器。让我们来编写和发送GET和POST请求。
GET Request
你可以在下拉菜单中选择GET,在URL栏中输入URL ( localhost:8000/taskmanagement/ ),然后点击发送按钮。Postman将在输出Body部分显示信息。下面的屏幕截图显示了JSON输出响应。
使用Postman的HTTP GET请求
你可以点击 “页眉 “标签,查看页眉的详细信息。分享下面的屏幕截图。
Header
POST Request
现在让我们使用Postman GUI工具发送一个POST请求。按照下面的步骤进行。
1.从下拉菜单中选择POST动词。
2.在URL字段中输入URL ( localhost:8000/taskmanagement/ )
3.选择车身部分(在输入部分)。
4.勾选原始单选按钮,同时在GraphQL按钮右侧的下拉菜单中选择JSON。
5.输入以下几行{“task_name”: “Task 01”, “task_desc”: “Desc 01”, “category”: “Writing”, “priority”: “Medium”, “created_date”: “2020-11-02 13:02:20.890678”, “deadline”: “2020-10-29 00:00.000000+00:00”, “status”: “Completed”, “payment_done”:”true”}在正文中(输入部分)。并点击发送。
分享下面的截图。
Summary
在这篇文章中,我们为HTTP请求创建了一个Django API视图,通过RESTFul网络服务与SQLite数据库进行交互。我们使用了GET、POST、PUT和DELETE等HTTP动词。我们已经看到了如何使用命令行工具(curl和HTTPie)和GUI工具(POSTMAN)来发送和编写HTTP请求。