使用Django REST Framework创建REST API
在本教程中,我们将学习一种流行且广泛使用的行业标准数据交换格式——REST API。它是最常用的数据交换技术。我们将解释如何使用Django在Python中创建REST API。在深入探讨这个主题之前,让我们了解REST的概念以及它与传统格式的区别。了解REST将帮助我们更好地理解。让我们简要介绍一下REST API。
什么是REST API
REST是表示状态转移(Representational State Transfer)的首字母缩写,它是一种标准化的提供数据给其他应用程序的方式。换句话说,它用于构建和与Web服务通信。它是跨应用程序传输数据的最佳方式,并且可以被应用程序使用。它规定了Web上的资源以JSON、HTML或XML的形式呈现。有时,API也被用于在其他应用程序中修改数据。
API是应用程序编程接口(Application Programming Interface)的首字母缩写,它定义了不同软件组件之间的交互。Web API决定了请求被发送给组件的具体内容。例如,我们定义一个终点来获取特定分支的学生列表。它还用于定义请求的方式以及它们的预期响应。
以下是一些重要的REST API请求方法。
- GET :它是从组件中获取数据的最常用方法。根据我们所访问的终点和传递的参数,它从API返回一些数据。
- POST :它创建新的记录并在数据库中更新新创建的记录。
- PUT :它将新的记录放在给定的URI上。如果记录存在,则更新记录。如果记录不存在,则创建一个新记录。
- PATCH :它在给定的URI上接受一个或多个字段。它用于更新一个或多个数据字段。如果记录存在,则更新记录。如果记录不存在,则创建一个新记录。
- DELETE :它删除给定URI上的记录。
通常,API是一个用于访问数据库的窗口。API负责根据数据库查询获取或更新记录。我们以JSON格式接收静态响应。
REST APIs在软件开发中非常常见,对于开发人员来说,这是一项最受需求和必不可少的技能。API是应用程序之间甚至程序内部进行通信的方式。
许多应用程序依赖于REST APIs。例如,REST API允许前端与后端通信。例如,如果我们使用Django后端部署应用程序,将需要一个API来允许React从数据库中获取信息。
通过实践来进一步了解REST API。现在让我们对Django REST Framework进行简要介绍。
什么是Django Rest Framework
Django Rest Framework(DRF)是在Django之上构建的一个包,用于创建Web API。它提供了Django最丰富的功能,包括对象关系映射(ORM),以一种Pythonic的方式与数据库进行交互。
因此,Python对象无法通过网络发送,因此我们需要将Django模型转换为其他格式(如JSON、XML)以及相反。这个过程被称为序列化,而Django REST框架使其变得非常简单。
DRF允许我们以REST API的形式表示其功能Django应用程序。这样做非常简单。
如果你想深入了解DRF,可以阅读有关如何使用核心Django框架创建REST API的文章。
开始使用Django Rest Framework
由于我们知道Django是一个流行的用于快速开发安全可扩展的Web服务的网络框架。我们的步骤1是创建虚拟环境并在其中安装所有依赖项。让我们创建虚拟环境。
python3 n venv myenv
现在我们需要进入环境中的scripts目录并运行以下命令来激活虚拟环境。
在Mac或Linux上
. myenv/bin/activate
在窗户上
myenv\scripts\activate
现在,通过pip命令安装Django
pip install django
我们准备好创建Django项目和应用程序。
我们已经创建了一个项目和应用程序;它必须在settings.py文件中注册。同时,在应用程序列表中添加 rest_framework ,以让Django知道我们将使用Django REST Framework。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'sample_api',
]
一旦我们注册了应用程序,我们就可以迁移(初始化数据库)并创建一个超级用户来跟踪数据库。
#to initialize the database
python manage.py migrate
# to open the prompt
python manage.py createsuperuser
现在,请输入必要的详细信息并创建超级用户。我们已经准备好启动可以接受请求的服务器。
python manage.py runserver
使用DRF在Django中创建一个REST API
我们已经设置好了Django项目;现在,我们可以开始开发领域模型和业务逻辑。
首先,我们创建一个简单的学生模型来表示学生的详细信息。在sample_app/model.py文件中,我们定义了我们的模型。
sample_app/models.py
from django.db import models
# Create your models here.
class Students(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
address = models.CharField(max_length=200)
roll_number = models.IntegerField()
mobile = models.CharField(max_length=10)
def __str__(self):
return self.first_name + " " + self.last_name
我们已经创建了我们的模型,并将这个模型注册到Django中。为了在管理员面板中看到这个模型,我们将在 sample_app/admin.py 中添加以下行。
from django.contrib import admin
from .models import Students
# Register your models here.
admin.site.register(Students)
我们的新模型已经注册。我们需要执行 makemigration 命令以在数据库中反映出Student表。在终端中运行以下命令。
python3 manage.py makemigrations
python3 manage.py migrate
在这里我们可以使用我们的模型。Web应用经常在两端之间传输模型数据。
现在我们要实现DRF中最有用的功能之一, 序列化器。 让我们对序列化器有一个基本的了解。
什么是序列化器?
序列化器用于以JSON格式表示模型数据并将对象实例转换为更易传输的格式。它使得解析来自API的数据的过程变得简单。另一方面,反序列化器将JSON数据转换为我们的模型的对象实例。
我们将在sample_app中创建serializers.py文件,将一个模型对象转换为JSON格式,然后再发送响应。
serializers.py
from rest_framework import serializers
from .models import Students
class StudentSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(max_length=200, required=True)
last_name = serializers.CharField(max_length=200, required=True)
address = serializers.CharField(max_length=200, required=True)
roll_number = serializers.IntegerField()
mobile = serializers.CharField(max_length=10, required=True)
class Meta:
model = Students
fields = ('__all__')
serializers.py与Django中的Form类文件非常相似,包括在各个字段上设置验证标志,例如required、max_length和default。在上面的代码中,我们指定了所有字段都是必需的,如果用户没有提供任何字段,就会抛出错误。为了避免错误,我们可以传递默认值。
我们使用了 Modelserializer 类,与Django中的 ModelForm 类相同。也可以使用Serializers类创建序列化器。
from rest_framework import serializers
from .models import Students
class StudentSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(max_length=200, required=True)
last_name = serializers.CharField(max_length=200, required=True)
address = serializers.CharField(max_length=200, required=True)
roll_number = serializers.IntegerField()
mobile = serializers.CharField(max_length=10, required=True)
def create(self, validated_data):
"""
Create and return a new `Students` instance, given the validated data.
"""
return Students.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Students` instance, given the validated data.
"""
instance.first_name = validated_data.get('first_name', instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.address = validated_data.get('address', instance.address)
instance.roll_number = validated_data.get('roll_number', instance.roll_number)
instance.mobile = validated_data.get('mobile', instance.mobile)
instance.save()
return instance
如我们所见,有两种方法 create() 和 update() 方法,在调用 .save() 方法时定义如何创建或修改完全成熟的实例。我们可以使用任一方法创建序列化器。
创建视图
DRF允许我们为API创建基于类和基于函数的视图。我们将创建基于类的视图。
我们将使用APIView类,它是Django View类的子类。我们可以定义get()、post()、patch()和delete()方法来执行CRUD操作。
sample_app/views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Students
from .serializers import StudentSerializer
# Create your views here.
class StudentView(APIView):
def get(self, request, *args, **kwargs):
result = Students.objects.all()
serializers = StudentSerializer(result, many=True)
return Response({'status': 'success', "students":serializers.data}, status=200)
def post(self, request):
serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
else:
return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
正如我们所看到的,首先,我们从数据库中获取所有记录,并使用StudentSerializers对它们进行序列化。在post()方法中,我们使用StudentSerializers从request.data创建序列化对象。POST请求将数据发送到服务器中并封装在请求主体中。它用于在数据库中创建一个新记录。如果is_valid()方法返回True,则请求的数据有效,并调用save()方法创建一个新记录。如果返回False,则抛出错误。
响应必须使用要返回的数据进行初始化。这些数据可以是任何类型的Python对象的实例,如bool、str、dict等。
为视图设置端点
首先,我们需要使用以下代码将应用的端点初始化到项目的urls.py中。
config/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('sample_app.urls'))
]
我们可以将 StudentView 类注册为用户的视图。添加它的目的不是为了实现,而是作为请求处理程序。
让我们为 get() 和 post() 方法创建端点。需要在 sample_app 文件夹中创建urls.py文件。我们将在sample_app/urls.py文件中添加以下代码。
sample_app/urls.py
from .views import StudentView
from django.urls import path
urlpattern = [
path('basic/', StudentView.as_view())
]
在上面的代码中, path() 的第一个参数表示我们的视图应该被访问的子路径,第二个参数是我们在views.py文件中创建的类名。
现在我们可以开始使用我们的API了。
运行服务器
现在,我们运行服务器并使用我们创建的api/basic/端点。
python manage.py runserver
当我们访问本地服务器http://127.0.0.1:8000/时,它将显示我们的端点,我们可以检查我们定义的端点。
http://127.0.0.1:8000/api/basic/是测试get()和post()方法的实际路径。首先我们验证get()方法。
{
"status": "success",
"students": [
{
"id": 1,
"first_name": "Rohit",
"last_name": "Sharma",
"address": "Agra",
"roll_number": 101,
"mobile": "1234567"
},
{
"id": 2,
"first_name": "Sachin",
"last_name": "Malhotra",
"address": "Agra",
"roll_number": 102,
"mobile": "7672573"
},
{
"id": 3,
"first_name": "Arun",
"last_name": "Tiwari",
"address": "Jamshedpur",
"roll_number": 103,
"mobile": "67654678"
},
{
"id": 4,
"first_name": "Tusar",
"last_name": "Srivastava",
"address": "Varanasi",
"roll_number": 104,
"mobile": "87975890"
}
]
}
视图处理 get() 请求,并以JSON格式将可用数据返回给客户端。
让我们测试POST端点。 post() 将从用户那里获取数据,并将其作为新记录添加到数据库中。 DRF将生成自动生成的可浏览API。
我们将传递输入字段,以便我们能够向端点发送一个POST请求。
{
"status": "success",
"data": {
"id": 5,
"first_name": "Divya",
"last_name": "Saxsena",
"address": "Noida",
"roll_number": 105,
"mobile": "87975812"
}
}
新数据已添加到数据库中,这意味着我们的POST方法正常工作。
现在我们获取数据;它将在浏览器中显示全部结果。
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"status": "success",
"students": [
{
"id": 1,
"first_name": "Rohit",
"last_name": "Sharma",
"address": "Agra",
"roll_number": 101,
"mobile": "1234567"
},
{
"id": 2,
"first_name": "Sachin",
"last_name": "Malhotra",
"address": "Agra",
"roll_number": 102,
"mobile": "7672573"
},
{
"id": 3,
"first_name": "Arun",
"last_name": "Tiwari",
"address": "Jamshedpur",
"roll_number": 103,
"mobile": "67654678"
},
{
"id": 4,
"first_name": "Tusar",
"last_name": "Srivastava",
"address": "Varanasi",
"roll_number": 104,
"mobile": "87975890"
},
{
"id": 5,
"first_name": "Divya",
"last_name": "Saxsena",
"address": "Noida",
"roll_number": 105,
"mobile": "87975812"
}
]
}
请求数据验证
如果我们漏掉任何必需的数据或输入错误的条目会怎么样?例如一个罗尔号的字符串,这个已经被定义为整数。让我们看下面的示例。
输入
{
"first_name": "Divankar",
"last_name": "Saxsena",
"address": "Noida",
"roll_number": "105",
"mobile": "87975812"
}
输出:
{
"status": "error",
"data": {
"roll_number":
[
"A valid integer is required"
]
}
}
它发出错误,因为我们传递了错误类型的值给 roll_number。 DRF的自动数据验证是一个很好的功能。它会因为我们传递了错误的值类型给 roll_number。 如果我们遗漏了任何字段,它会显示以下错误。
{
"status": "error",
"data": {
"address": [
"This field is required."
]
}
}
然而,我们也可以通过自定义验证器来定义自定义验证规则。
修改Get请求处理程序
在前面的Get请求示例中,我们获取了表中的所有记录。我们也可以通过将它的id作为参数来检索表中的特定实体。我们获取单个记录并传递给 StudentSerializer() ,这次我们不会传递 many=True ,因为我们只传递单个记录。我们将代码更改如下。
sample_app/views.py
class StudentView(APIView):
def get(self, request, id):
result = Students.objects.get(id=id)
if id:
serializers = StudentSerializer(result)
return Response({'success': 'success', "students":serializers.data}, status=200)
result = Students.objects.all()
serializers = StudentSerializer(result, many=True)
return Response({'status': 'success', "students":serializers.data}, status=200)
正如我们所观察到的, StudentSerializer(result, many=True) 已经以JSON格式返回一个对象列表序列化的数据。或者,我们可以通过URL传递id参数- http://127.0.0.1:8000/api/basic/1/。这里我们将1作为id传递,为了处理这个请求,我们需要修改urls.py。我们添加如下的路径。
sample_app/urls.py
from .views import StudentView
from django.urls import path
urlpatterns = [
path('basic/', StudentView.as_view()),
path('basic/<int:id>/', StudentView.as_view())
]
当我们访问 http://127.0.0.1:8000/api/basic/1/ 时,将会显示以下结果。
{
"success": "success",
"students": {
"id": 1,
"first_name": "Rohit",
"last_name": "Sharma",
"address": "Agra",
"roll_number": 101,
"mobile": "1234567"
}
}
我们只得到一个JSON响应,而不是一个对象列表。
更新值的Patch请求处理程序
到目前为止,我们已经实现了获取和添加记录的功能。现在,我们将创建用于更新已经存在于数据库中的记录的端点。我们可以使用针对特定id的POST请求来更新记录。然后,我们检索对象,更新其值,并将其保存在相同的id下,从而保持更改的持久性。
APIView 类提供了 patch() 方法来处理PATCH请求并更新数据。
让我们将views.py文件更新如下。
Class StudentView(APIView):
def patch(self, request, id):
result = Students.objects.get(id=id)
serializer = StudentSerializer(result, data = request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "error", "data": serializer.errors})
我们想要强调的行
serializer = StudentSerializer(result, data=request.data, partial=True)
让我们理解上面的行
- 获取要更新的给定ID记录。
- 传递给StudentSerializer以将其转换为JSON。
- 从请求中接收到的数据。
- “partial=True”表示这可能不包含我们的Student模型的所有字段。
我们需要传递实际的实例,我们将使用”get()”函数首先检索资源,然后更新它。现在,我们将发送补丁请求到http://127.0.0.1:8000/api/basic/1/,并更新我们的项目。
我们将”last_name”从”Sharma”更改为”Yadav”。
{
"id": 1,
"first_name": "Rohit",
"last_name": "Yadav",
"address": "Agra",
"roll_number": 101,
"mobile": "1234567"
}
响应显示更新后的last_name。我们可以通过访问http://127.0.0.1:8000/api/basic/1/update端点进行验证。
{
"success": "success",
"students": {
"id": 1,
"first_name": "Rohit",
"last_name": "Yadav",
"address": "Agra",
"roll_number": 101,
"mobile": "1234567"
}
}
在这里,我们可以看到我们的数据已成功更新。
删除实体 DELETE请求处理程序
用户还想要从数据库中记录一些条目。为此,APIView类提供了delete()方法,该方法按照给定的id删除记录。对于这个目的,我们不需要使用序列化器,因为数据和具体对象之间没有转换。在这里,我们可以使用get_object_or_404()函数,而不是使用Students.objects.get(),如果给定的id不存在,它会自动返回404错误。
让我们理解delete()方法的以下实现。
sample_app/views.py
from django.shortcuts import get_object_or_404
class StudentAPI(APIView):
def delete(self, request, id=None):
result = get_object_or_404(Students, id=id)
result.delete()
return Response({"status": "success", "data": "Record Deleted"})
当我们重新启动服务器时,API浏览器上将显示DELETE按钮。当我们点击DELETE按钮时,它会从数据库中删除该特定id的记录。
删除记录 http://127.0.0.1:8000/api/basic/1/ 后,将显示以下响应。
{
"status": "success",
"data": "Record Deleted"
}
当我们访问http://127.0.0.1:8000/api/basic/时,此记录不再存在。
我们使用DRF实现了CRUD API。
CRUD API完整代码
以下是我们在本教程中实现的CRUD操作的完整代码。
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Students
from .serializers import StudentSerializer
from django.shortcuts import get_object_or_404
# Create your views here.
class StudentView(APIView):
def get(self, request, id):
result = Students.objects.get(id=id)
if id:
serializers = StudentSerializer(result)
return Response({'success': 'success', "students":serializers.data}, status=200)
result = Students.objects.all()
serializers = StudentSerializer(result, many=True)
return Response({'status': 'success', "students":serializers.data}, status=200)
def post(self, request):
serializer = StudentSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
else:
return Response({"status": "error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, id):
result = Students.objects.get(id=id)
serializer = StudentSerializer(result, data = request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "error", "data": serializer.errors})
def delete(self, request, id=None):
result = get_object_or_404(Students, id=id)
result.delete()
return Response({"status": "success", "data": "Record Deleted"})
sample_app/urls.py
from .views import StudentView
from django.urls import path
urlpatterns = [
path('basic/', StudentView.as_view()),
path('basic//', StudentView.as_view()),
path('basic//update/', StudentView.as_view())
结论
本教程详细描述了DRF的概念以及如何在Django中构建一个 RESTful API。在本教程中,我们创建了一个项目并添加 一个示例应用 。我们创建了Student模型和StudentSerializer来处理我们模型的序列化和反序列化。这是一个CRUD API,我们有get()、post()、patch()和delete()这些重要的请求处理程序。通过参考本教程,您可以为练习目的创建购物网站的CRUD API。