https://blog.csdn.net/weixin_46451496/article/details/105285132

一 下载djangorestframework

  1. pip install djangorestframework

二 创建应用

在django中创建应用api

  1. python manage.py startapp api

此时项目结构:

  1. mysite/
  2. manage.py
  3. mysite/
  4. __init__.py
  5. settings.py
  6. urls.py
  7. asgi.py
  8. wsgi.py
  9. api/
  10. __init__.py
  11. admin.py
  12. apps.py
  13. migrations/
  14. __init__.py
  15. models.py
  16. tests.py
  17. views.py

三 配置

在项目的settings.py中将创建的应用api以及rest_framework添加到INSTALLED_APPS 中:

  1. INSTALLED_APPS = [
  2. ...
  3. 'api',
  4. 'rest_framework',
  5. ...
  6. ]

四 创建模型类

在应用api/models.py中添加如下代码:

  1. from django.db import models
  2. class Inventory(models.Model):
  3. """库存类"""
  4. type = models.CharField(max_length=125)
  5. m_number = models.CharField(max_length=125)
  6. def __str__(self):
  7. return self.m_number
  8. class Meta:
  9. db_table = 'inventory'
  10. verbose_name = '库存'
  11. @classmethod
  12. def get_all(cls):
  13. return cls.objects.all()

4.1 执行数据库迁移

前提是将模型api添加到INSTALLED_APPS中,否则迁移不成功

  1. python manage.py makemigrations
  2. python manage.py migrate

image.png
此时数据库创建了对应的数据表(apiproinfo)—>数据库表命名是django默认命名方式:应用名模型类名小写
image.png

4.2 将测试数据插入数据库表中

五 新建Serializer

DRF框架支持两种实现数据接口的方式,一种是FBV(基于函数的视图),另一种是CBV(基于类的视图)。我们先看看*CBV的方式如何实现数据接口

首先我们要定义一些序列化程序。我们创建一个名为 api/serializers.py的文件,来用作我们的数据表示。
api/serializers.py

  1. from rest_framework import serializers
  2. from inventory.models import Inventory
  3. class InventorySerializer(serializers.ModelSerializer):
  4. class Meta:
  5. model = Inventory
  6. fields = ('type')
  • fields里面是要显示的字段
  • Serializer 实现继承HyperlinkedModelSerializer

请注意!!!
在这个例子中我们用到了超链接关系,使用 HyperlinkedModelSerializer。也可使用ModelSerializer,但超链接是好的RESTful设计。

上述代码是指定显示部分字段,如果显示全部字段:

  1. from rest_framework import serializers
  2. from inventory.models import Inventory
  3. class InventorySerializer(serializers.ModelSerializer):
  4. class Meta:
  5. model = Inventory
  6. fields = '__all__'

重要的是要记住,ModelSerializer类并不会做任何特别神奇的事情,它们只是创建序列化器类的快捷方式:

  • 一组自动确定的字段。
  • 默认简单实现的create()和update()方法。

注意:当使用HyperlinkedModelSerializer的时候不能使用 fields = '__all__',不然会报错,错误信息如下:

  1. Could not resolve URL for hyperlinked relationship using view name "proinfo-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

解决办法:
(方法一)不使用HyperlinkedModelSerializer,而使用ModelSerializer,
(方法二)当要显示所有字段时,全部写在fields里面


六 基于类的视图(CBV)

使用基于类的视图

views.py

  1. from inventory.serializers import InventorySerializer
  2. class InventoryList(APIView):
  3. def get(self,request,format = None):
  4. snippets = Inventory.objects.all()
  5. serializer = InventorySerializer(snippets, many=True)
  6. return Response(serializer.data)
  7. def post(self,request,format=None):
  8. serializer = InventorySerializer(data=request.data)
  9. if serializer.is_valid():
  10. serializer.save()
  11. return Response(serializer.data, status=status.HTTP_201_CREATED)
  12. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

应用的urls.py

  1. from inventory import views
  2. urlpatterns = [
  3. path('',views.InventoryList.as_view(),name='inventory_list'),
  4. ]

serializers.py

  1. from rest_framework import serializers
  2. from inventory.models import Inventory
  3. class InventorySerializer(serializers.ModelSerializer):
  4. class Meta:
  5. model = Inventory
  6. fields = '__all__'

使用混合(mixins)

使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
到目前为止,我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。

views.py

  1. from inventory.models import Inventory
  2. from inventory.serializers import InventorySerializer
  3. from rest_framework import status, mixins, generics
  4. class InventoryList(mixins.ListModelMixin,
  5. mixins.CreateModelMixin,
  6. generics.GenericAPIView):
  7. queryset = Inventory.objects.all()
  8. serializer_class = InventorySerializer
  9. def get(self, request, *args, **kwargs):
  10. return self.list(request, *args, **kwargs)
  11. def post(self, request, *args, **kwargs):
  12. return self.create(request, *args, **kwargs)

urls.py同上

使用通用的基于类的视图

通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。

  1. from rest_framework import generics
  2. class InventoryList(generics.ListCreateAPIView):
  3. queryset = Inventory.objects.all()
  4. serializer_class = InventorySerializer

如此简洁。我们可以使用很多现成的代码,让我们的代码看起来非常清晰、简洁,地道的Django。


用于查询数据库中数据
打开api/views.py

  1. from rest_framework import viewsets
  2. from .models import ProInfo
  3. from .serializers import ProInfoSerializer
  4. # Create your views here.
  5. class ProInfoViewSet(viewsets.ModelViewSet):
  6. queryset = ProInfo.objects.all()[:10] # 查询数据表前10条信息
  7. # 指定序列化对应的类
  8. serializer_class = ProInfoSerializer

其中:

  1. queryset指定数据源serializer_class指定要序列化的类,即上面自定义的序列化类:ProInfoSerializer

7 启动项目

  1. python manage.py runserver

输入:http://127.0.0.1:8000/inventory/ 可以看到当前应用inventory下面的所有的数据接口(如果写了多个的话)
image.png

8 补充:基于函数的视图(FBV)

api/serializers.py

  1. from rest_framework import serializers
  2. from inventory.models import Inventory
  3. class InventorySerializer(serializers.ModelSerializer):
  4. class Meta:
  5. model = Inventory
  6. fields = '__all__'

api/views.py

  1. from django.http import HttpResponse
  2. from django.views.decorators.csrf import csrf_exempt
  3. from rest_framework import status
  4. from rest_framework.decorators import api_view
  5. from rest_framework.parsers import JSONParser
  6. from rest_framework.response import Response
  7. from inventory.models import Inventory
  8. from inventory.serializers import InventorySerializer
  9. @api_view(['GET','POST'])
  10. def inventory_list(request):
  11. """
  12. 列出所有的code inventory,或创建一个新的inventory。
  13. """
  14. if request.method == 'GET':
  15. snippets = Inventory.objects.all()
  16. serializer = InventorySerializer(snippets, many=True)
  17. return Response(serializer.data)
  18. elif request.method == 'POST':
  19. serializer = InventorySerializer(data=request.data)
  20. if serializer.is_valid():
  21. serializer.save()
  22. return Response(serializer.data, status=status.HTTP_201_CREATED)
  23. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

项目的/urls.py

  1. from django.contrib import admin
  2. from django.urls import path,include
  3. urlpatterns = [
  4. path('admin/', admin.site.urls),
  5. path('inventory/', include('inventory.urls')),
  6. ]

应用的/urls.py

  1. from django.urls import path
  2. from inventory import views
  3. app_name = 'inventory'
  4. urlpatterns = [
  5. path('',views.inventory_list,name='inventory_list'),
  6. path('<str:pk>/', views.inventory_detail,name='inventory_detail'),
  7. ]

访问:http://127.0.0.1:8000/inventory/

9 请求与响应

https://q1mi.github.io/Django-REST-framework-documentation/tutorial/2-requests-and-responses_zh/

九 RESTful架构和DRF进阶

https://github.com/jackfrued/Python-100-Days/blob/master/Day41-55/50.RESTful%E6%9E%B6%E6%9E%84%E5%92%8CDRF%E8%BF%9B%E9%98%B6.md

9.1 分页

在使用GET请求获取资源列表时,我们通常不会一次性的加载所有的数据,除非数据量真的很小。大多数获取资源列表的操作都支持数据分页展示,也就说我们可以通过指定页码(或类似于页码的标识)和页面大小(一次加载多少条数据)来获取不同的数据。我们可以通过对QuerySet对象的切片操作来实现分页,也可以利用Django框架封装的Paginator和Page对象来实现分页。使用DRF时,可以在Django配置文件中修改RESTFRAMEWORK并配置默认的分页类和页面大小来实现分页,如下所示。
**_settings.py
**

  1. REST_FRAMEWORK = {
  2. # 一页十条
  3. 'PAGE_SIZE': 10,
  4. 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
  5. }

效果:
image.png