在本文中,我们将讨论初学者的Django REST框架课程,有关初学者的Django REST框架课程的更多信息,您可以查看本文的完整视频。
什么是RESTFull API
RESTful API充当通过Web服务进行通信的两台计算机之间的翻译器。如果您熟悉API的概念,这就像一个API,但是它在RESTful Web服务上运行,并且两个应用程序试图通过网络或Internet相互通信使用该API。
Web开发人员对REST API进行编程,使服务器可以从应用程序接收数据。这些应用程序可以是Web应用程序,Android / iOS应用程序等。RESTfulAPI返回JSON文件,该文件可以由各种设备解释。
什么是Django REST框架
Django REST框架是用于构建Web API的功能强大且灵活的工具包。
您可能要使用REST框架的一些原因:
1.Web可浏览的API对于您的开发人员来说是一个巨大的可用性胜利。
2.身份验证策略,包括OAuth1a和OAuth2的软件包。
3、支持ORM和非ORM数据源的序列化。
4、完全可自定义-如果您不需要更强大的功能,只需使用基于功能的常规视图即可。
5、大量的文档和强大的社区支持。
6、由Mozilla,Red Hat,Heroku和Eventbrite等国际知名公司使用和信任。
Also you can read more django articles
1: Django Pagination Complete Example
2: Django Sending Email to Gmail Account
3: Build News Application in Django
5: Django User Authentication Framework
安装:
pip install djangorestframework
创建一个工程:
django–admin startproject MyProject
创建一个app:
python manage.py startapp api_basic
创建管理员用户:
python manage.py createsuperuser
在settings.py中增加:
1 2 3 4 5 |
INSTALLED_APPS = ( ... 'rest_framework', 'api_basic', ) |
构建api的重要概念是序列化程序,现在您需要在创建的应用程序中以serializer.py的名称创建一个新的python文件,现在我们不对该文件添加任何内容。
什么是序列化器
在将数据发送到客户端之前,我们需要将数据序列化为JSON。 首先,我们需要开始使用Web API,是提供一种将数据实例序列化和反序列化为json等表示形式的方法。 为此,我们可以声明与Django表单非常相似的序列化器。
现在是时候创建模型了,现在您需要在应用中打开models.py文件并添加此代码,基本上,我们将创建Article模型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from django.db import models # Create your models here. class Article(models.Model): title = models.CharField(max_length=100) author =models.CharField(max_length=100) email = models.EmailField(max_length=100) date = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title |
数据库迁移:
python manage.py makemigrations
python manage.py migrate
然后在admin.py中注册model,如下:
1 2 3 4 5 6 7 8 |
#admin.py from django.contrib import admin from .models import Article # Register your models here. admin.site.register(Article) |
好的,现在我们要在已经创建的serializer.py文件中添加代码。 您可以使用不同的串行器,我们将逐步进行此操作。
如果使用此方法,则需要在seriaizer文件中指定所有模型字段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#serializers.py from rest_framework import serializers from .models import Article class ArticleSerializer(serializers.Serializer): title = serializers.CharField(max_length=100) author = serializers.CharField(max_length=100) email = serializers.EmailField(max_length=100) date = serializers.DateTimeField() def create(self, validated_data): # Create and return a new `Article` instance, given the validated data. return Article.objects.create(validated_data) def update(self, instance, validated_data): #Update and return an existing `Article` instance, given the validated data. instance.title = validated_data.get('title', instance.title) instance.author = validated_data.get('author', instance.author) instance.email = validated_data.get('email', instance.email) instance.date = validated_data.get('date', instance.date) instance.save() return instance |
序列化程序类的第一部分定义了要进行序列化/反序列化的字段。 create()和update()方法定义了在调用serializer.save()时如何创建或修改完整实例。
序列化器类与Django Form类非常相似,并且在各个字段上包括相似的验证标志,例如required,max_length和default。
python manage.py shell
1 2 3 4 5 6 7 8 |
#导入 In [1]: from api_basic.models import Article In [2]: from api_basic.serializers import ArticleSerializer In [3]: from rest_framework.renderers import JSONRenderer In [4]: from rest_framework.parsers import JSONParser |
现在创建一个article并保存:
1 2 3 4 |
In [5]: a = Article(title = 'New Article', author ='Parwiz', email = 'par@gmail.com', ) ...: In [6]: a.save() |
如果您查看django管理面板,则可以看到我有一篇新文章。 您也可以添加所需的文章。
现在让我们序列化文章,我们将再次使用django shell。
1 2 3 4 5 |
In [9]: serializer = ArticleSerializer(a) In [10]: serializer.data Out[10]: {'title': 'Article Title', 'author': 'John', 'email': 'john@gmail.com', 'date': '2020-05-24T09:14:02.081688Z'} |
至此,我们已经将模型实例转换为Python本机数据类型。 为了完成序列化过程,我们将数据渲染到json中。
1 2 3 4 |
In [11]: content = JSONRenderer().render(serializer.data) ...: content Out[11]: b'{"title":"Article Title","author":"John","email":"john@gmail.com","date":"202 0-05-24T09:14:02.081688Z"}' |
这是我们序列化的数据。
我们还可以序列化查询集而不是模型实例。 为此,我们只需在序列化器参数中添加many = True标志。
1 2 |
In [13]: serializer = ArticleSerializer(Article.objects.all(), many=True) ...: serializer.data |
ModelSerializers
我们的ArticleSerializer类正在复制Article模型中也包含的许多信息。 如果我们可以使代码更简洁,那将是很好的。 就像Django提供Form类和ModelForm类一样,REST框架同时包含Serializer类和ModelSerializer类。
让我们看一下使用ModelSerializer类重构序列化器
1 2 3 4 5 6 7 8 9 |
from rest_framework import serializers from .models import Article class ArticleSerializer(serializers.ModelSerializer): class Meta: model = Article fields = ['id', 'title', 'author'] |
让我们看看如何使用新的Serializer类编写一些API视图。 目前,我们将不使用REST框架的任何其他功能,而只是将视图编写为常规Django视图。
因此,现在打开您的views.py,并添加此代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#views.py from django.shortcuts import render from django.http import HttpResponse, JsonResponse from rest_framework.parsers import JSONParser from .models import Article from .serializers import ArticleSerializer @csrf_exempt def article_list(request): """ List all code articles, or create a new Article. """ if request.method == 'GET': articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == 'POST': data = JSONParser().parse(request) serializer = ArticleSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400) |
因此,现在我们将在您的应用(api_basic)中以urls.py的名称创建一个新的python文件。
另外,您需要像这样将文件添加到您的主urls.py中。
1 2 3 4 5 6 7 8 |
#urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('api_basic.urls')) ] |
运行项目:
python manage.py runserver
访问:http://localhost:8000/article/
https://codeloop.org/wp-content/uploads/2020/05/django-rest-framework.png
也可用postman访问:
https://codeloop.org/wp-content/uploads/2020/05/django-api-basics.png
您也可以发布文章。 但请确保已在视图函数顶部添加了csrf_exempt,因为我们已经这样做了。
我们还需要一个与单个文章相对应的视图,该视图可用于检索,更新或删除该文章。 因此,现在打开您的views.py,我们需要添加一个新的视图功能。 在此之前,我们已经为文章的获取和发布创建了视图功能,但这是用于删除和更新文章。 还要注意,这些都是基于函数的api视图,但是当我们使用基于类的视图或泛型视图时,就不会使用这些代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#views.py @csrf_exempt def article_detail(request, pk): """ Retrieve, update or delete article. """ try: article = Article.objects.get(pk=pk) except Article.DoesNotExist: return HttpResponse(status=404) if request.method == 'GET': serializer = ArticleSerializer(article) return JsonResponse(serializer.data) elif request.method == 'PUT': data = JSONParser().parse(request) serializer = ArticleSerializer(article, data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data) return JsonResponse(serializer.errors, status=400) elif request.method == 'DELETE': article.delete() return HttpResponse(status=204) |
打开app下的urls.py,增加如下:
1 2 3 4 5 6 7 8 9 10 11 |
#urls.py from django.urls import path from .views import article_list, article_detail urlpatterns = [ path('article/', article_list), path('detail/<int:pk>/', article_detail), ] |
现在,您可以使用它检索特定的id文章,也可以更新文章或删除文章。
https://codeloop.org/wp-content/uploads/2020/05/buil-api-with-django.png
在基于函数的视图中使用api_view装饰器
Using api_view() Decorator in Function BasedView)
您还可以将装饰器与基于函数api的视图一起使用,例如,可以使用api_view(),此功能的核心是api_view装饰器,该装饰器具有您的视图应响应的HTTP方法的列表。 还可以使用此装饰器访问django可浏览api视图。
现在,我们将像这样更改views.py函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
#views.py from .models import Article from .serializers import ArticleSerializer from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status # Create your views here. @api_view(['GET', 'POST']) def article_list(request): """ List all articles, or create a new article. """ if request.method == 'GET': articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = ArticleSerializer(data=request.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) @api_view(['GET', 'PUT', 'DELETE']) def article_detail(request, pk): """ Retrieve, update or delete article. """ try: article = Article.objects.get(pk=pk) except Article.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = ArticleSerializer(article) return Response(serializer.data) elif request.method == 'PUT': serializer = ArticleSerializer(article, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': article.delete() return Response(status=status.HTTP_204_NO_CONTENT) |
如果您访问http:// localhost:8000 / article /,则可以从django rest框架中看到可浏览的api,具有发布文章,获取文章,检索文章,删除文章和更新文章的相同功能。
https://codeloop.org/wp-content/uploads/2020/05/django-browsable-api-view.png
Class Based API View
好的,到目前为止,我们已经学习了有关django rest框架的一些基础知识,并且已经创建了一些基于api视图的函数示例。 现在该讨论Django中基于类的api视图了。 REST框架提供了APIView类,该类继承了Django的View类。 使用APIView类与使用常规View类几乎相同,通常,传入的请求将分派到适当的处理程序方法,例如.get()或.post()。 另外,可以在类上设置许多属性,以控制API策略的各个方面。
好的,现在我们将再次对views.py进行更改,我已经从views.py中删除了所有代码,因为通过使用基于类的api视图,我不需要该代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#views.py from .models import Article from .serializers import ArticleSerializer from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status class ArticleAPIView(APIView): def get(self, request): articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) def post(self, request): serializer = ArticleSerializer(data=request.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) class ArticleDetails(APIView): def get_object(self, id): try: return Article.objects.get(id=id) except Article.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) def get(self, request, id): article = self.get_object(id) serializer = ArticleSerializer(article) return Response(serializer.data) def put(self, request,id): article = self.get_object(id) serializer = ArticleSerializer(article, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, id): article = self.get_object(id) article.delete() return Response(status=status.HTTP_204_NO_CONTENT) |
另外,您还需要在urls.py文件中进行更改,因为现在我们使用的是基于类的视图。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#urls.py from django.urls import path from .views import ArticleAPIView, ArticleDetails urlpatterns = [ path('article/', ArticleAPIView.as_view()), path('detail/<int:id>/', ArticleDetails.as_view()), ] |
如果您访问http:// localhost:8000 / article /,则可以从django rest框架中看到可浏览的api,具有发布文章,获取文章,检索文章,删除文章和更新文章的相同功能。 但是这次我们使用了基于类的api视图。
https://codeloop.org/wp-content/uploads/2020/05/article-view.png
Generic View And Mixins
基于类的视图的主要优点之一是它们允许您组成一些可重用行为的方式。 REST框架通过提供许多提供常用模式的预构建视图来利用此优势。 REST框架提供的通用视图使您可以快速构建与数据库模型紧密映射的API视图。如果通用视图不适合您的API需求,则可以下拉至使用常规APIView类,或者重用通用视图所使用的mixins和基类来组成您自己的可重用通用视图集。
好的,现在我们再次更改views.py,并删除先前的代码,使用此代码,您可以添加,获取,更新和删除数据。此外,还有用于不同功能的单独的mixin,例如发布文章,我们将使用CreateModelMixin,获取文章,我们将使用ListModelMixin,更新,我们使用UpdateModelMixin,以及删除,我们可以使用DestroyModelMixin。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#views.py from .models import Article from .serializers import ArticleSerializer from rest_framework import generics from rest_framework import mixins class GenericAPIView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin): serializer_class = ArticleSerializer queryset = Article.objects.all() lookup_field = 'id' def get(self, request, id = None): if id: return self.retrieve(request) else: return self.list(request) def post(self, request): return self.create(request) def put(self, request, id=None): return self.update(request, id) def delete(self, request, id): return self.destroy(request, id) |
urls.py修改:
1 2 3 4 5 6 7 8 |
from django.urls import path from .views import GenericAPIView urlpatterns = [ path('generic/article/<int:id>/', GenericAPIView.as_view()), ] |
如果您访问http:// localhost:8000 / generic / article /,则可以从django rest框架中看到可浏览的api,具有发布文章,获取文章,检索文章,删除文章和更新文章的相同功能。 但是这次我们使用了通用视图和混合。
认证方式
身份验证是将传入请求与一组标识凭据(例如,请求来自的用户或与其进行签名的令牌)相关联的机制。然后,权限和限制策略可以使用这些凭据来确定是否应允许该请求。 REST框架提供了许多现成的身份验证方案,并且还允许您实现自定义方案。身份验证始终在视图的最开始,权限和限制检查发生之前以及允许任何其他代码继续执行之前运行。我们可以使用不同的身份验证,例如基本身份验证,令牌身份验证和会话身份验证。
基本身份验证:此身份验证方案使用HTTP基本身份验证,并针对用户的用户名和密码进行了签名。基本身份验证通常仅适用于测试。
令牌认证:此认证方案使用基于令牌的简单HTTP认证方案。令牌认证适用于客户端-服务器设置,例如本机台式机和移动客户端。
会话身份验证:此身份验证方案使用Django的默认会话后端进行身份验证。 会话身份验证适用于在与您的网站相同的会话上下文中运行的AJAX客户端。
对于身份验证的设置,您可以全局使用,也可以在python文件内部使用。 对于全局,您可以在settings.py文件中添加DEFAULT_AUTHENTICATION_CLASSES。
1 2 3 4 5 6 |
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ] } |
注意:我们没有全局使用,但是我们在python文件中添加了身份验证类。
因此,现在我们更改了views.py并添加了身份验证类。
首先,您需要导入所需的类。
1 2 |
from rest_framework.authentication import SessionAuthentication,TokenAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated |
新的views.py内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#views.py from .models import Article from .serializers import ArticleSerializer from rest_framework import generics from rest_framework import mixins from rest_framework.authentication import SessionAuthentication,TokenAuthentication, BasicAuthentication from rest_framework.permissions import IsAuthenticated class GenericAPIView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin): serializer_class = ArticleSerializer queryset = Article.objects.all() lookup_field = 'id' authentication_classes = [SessionAuthentication, BasicAuthentication] #authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def get(self, request, id = None): if id: return self.retrieve(request) else: return self.list(request) def post(self, request): return self.create(request) def put(self, request, id=None): return self.update(request, id) def delete(self, request, id): return self.destroy(request, id) |
我已评论了令牌身份验证,但是您可以这样使用,现在在这里我们将会话和基本身份验证一起使用,它将首先检查会话身份验证,然后再检查基本身份验证。
如果访问http:// localhost:8000 / generic / article / 6 /,则可以从django rest框架中看到可浏览的api。 但是这一次我们无法访问数据,因为我们使用了身份验证。
https://codeloop.org/wp-content/uploads/2020/05/django-session-basic-authentication.png
对于令牌认证,您可以从django管理面板手动创建令牌,然后再使用令牌进行认证。
Viewsets And Routers
ViewSet类只是基于类的View的一种,它不提供任何方法处理程序,例如.get()或.post(),而是提供诸如.list()和.create()的操作。 ViewSet的方法处理程序仅在使用.as_view()方法在最终确定视图时绑定到相应的操作。
实现视图集的方式有多种,第一种是可以编写自己的视图集。 现在我们要更改views.py。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#views.py from .models import Article from .serializers import ArticleSerializer from rest_framework import viewsets from rest_framework.response import Response from rest_framework import status from django.shortcuts import get_object_or_404 class ArticleViewSet(viewsets.ViewSet): def list(self, request): articles = Article.objects.all() serializer = ArticleSerializer(articles, many=True) return Response(serializer.data) def create(self, request): serializer = ArticleSerializer(data=request.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) def retrieve(self, request, pk=None): queryset = Article.objects.all() article = get_object_or_404(queryset, pk=pk) serializer = ArticleSerializer(article) return Response(serializer.data) |
同样需要加入路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#urls.py from django.urls import path, include from .views import ArticleViewSet from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register('article', ArticleViewSet, basename='article') urlpatterns = [ path('viewset/', include(router.urls)) ] |
如果您访问http:// localhost:8000 / viewset / article /,则可以从django rest框架中看到具有相同功能的可浏览api,但是这次我们使用了视图集和路由器。
https://codeloop.org/wp-content/uploads/2020/05/viewsets.png
我没有使用过更新和删除功能,但是您可以自己完成。
您通常不希望编写自己的视图集,而是要使用提供默认行为集的现有基类。 例如:
1 2 3 4 5 6 7 8 |
#views.py class ArticleViewSet(viewsets.ModelViewSet): """ A viewset for viewing and editing article instances. """ serializer_class = ArticleSerializer queryset = Article.objects.all() |
原文:https://codeloop.org/django-rest-framework-course-for-beginners/