https://blog.csdn.net/weixin_46451496/article/details/105285132
一 下载djangorestframework
pip install djangorestframework
二 创建应用
在django中创建应用api
python manage.py startapp api
此时项目结构:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
api/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
三 配置
在项目的settings.py中将创建的应用api以及rest_framework添加到INSTALLED_APPS 中:
INSTALLED_APPS = [
...
'api',
'rest_framework',
...
]
四 创建模型类
在应用api/models.py中添加如下代码:
from django.db import models
class Inventory(models.Model):
"""库存类"""
type = models.CharField(max_length=125)
m_number = models.CharField(max_length=125)
def __str__(self):
return self.m_number
class Meta:
db_table = 'inventory'
verbose_name = '库存'
@classmethod
def get_all(cls):
return cls.objects.all()
4.1 执行数据库迁移
前提是将模型api添加到INSTALLED_APPS中,否则迁移不成功
python manage.py makemigrations
python manage.py migrate
此时数据库创建了对应的数据表(apiproinfo)—>数据库表命名是django默认命名方式:应用名模型类名小写
4.2 将测试数据插入数据库表中
五 新建Serializer
DRF框架支持两种实现数据接口的方式,一种是FBV(基于函数的视图),另一种是CBV(基于类的视图)。我们先看看*CBV的方式如何实现数据接口
首先我们要定义一些序列化程序。我们创建一个名为 api/serializers.py的文件,来用作我们的数据表示。
api/serializers.py
from rest_framework import serializers
from inventory.models import Inventory
class InventorySerializer(serializers.ModelSerializer):
class Meta:
model = Inventory
fields = ('type')
- fields里面是要显示的字段
- Serializer 实现继承HyperlinkedModelSerializer
请注意!!!
在这个例子中我们用到了超链接关系,使用 HyperlinkedModelSerializer。也可使用ModelSerializer,但超链接是好的RESTful设计。
上述代码是指定显示部分字段,如果显示全部字段:
from rest_framework import serializers
from inventory.models import Inventory
class InventorySerializer(serializers.ModelSerializer):
class Meta:
model = Inventory
fields = '__all__'
重要的是要记住,ModelSerializer类并不会做任何特别神奇的事情,它们只是创建序列化器类的快捷方式:
- 一组自动确定的字段。
- 默认简单实现的create()和update()方法。
注意:当使用HyperlinkedModelSerializer的时候不能使用 fields = '__all__'
,不然会报错,错误信息如下:
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
from inventory.serializers import InventorySerializer
class InventoryList(APIView):
def get(self,request,format = None):
snippets = Inventory.objects.all()
serializer = InventorySerializer(snippets, many=True)
return Response(serializer.data)
def post(self,request,format=None):
serializer = InventorySerializer(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)
应用的urls.py
from inventory import views
urlpatterns = [
path('',views.InventoryList.as_view(),name='inventory_list'),
]
serializers.py
from rest_framework import serializers
from inventory.models import Inventory
class InventorySerializer(serializers.ModelSerializer):
class Meta:
model = Inventory
fields = '__all__'
使用混合(mixins)
使用基于类视图的最大优势之一是它可以轻松地创建可复用的行为。
到目前为止,我们使用的创建/获取/更新/删除操作和我们创建的任何基于模型的API视图非常相似。这些常见的行为是在REST框架的mixin类中实现的。
views.py
from inventory.models import Inventory
from inventory.serializers import InventorySerializer
from rest_framework import status, mixins, generics
class InventoryList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Inventory.objects.all()
serializer_class = InventorySerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
使用通用的基于类的视图
通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。
from rest_framework import generics
class InventoryList(generics.ListCreateAPIView):
queryset = Inventory.objects.all()
serializer_class = InventorySerializer
如此简洁。我们可以使用很多现成的代码,让我们的代码看起来非常清晰、简洁,地道的Django。
用于查询数据库中数据
打开api/views.py
from rest_framework import viewsets
from .models import ProInfo
from .serializers import ProInfoSerializer
# Create your views here.
class ProInfoViewSet(viewsets.ModelViewSet):
queryset = ProInfo.objects.all()[:10] # 查询数据表前10条信息
# 指定序列化对应的类
serializer_class = ProInfoSerializer
其中:
queryset指定数据源serializer_class指定要序列化的类,即上面自定义的序列化类:ProInfoSerializer
7 启动项目
python manage.py runserver
输入:http://127.0.0.1:8000/inventory/ 可以看到当前应用inventory下面的所有的数据接口(如果写了多个的话)
8 补充:基于函数的视图(FBV)
api/serializers.py
from rest_framework import serializers
from inventory.models import Inventory
class InventorySerializer(serializers.ModelSerializer):
class Meta:
model = Inventory
fields = '__all__'
api/views.py
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from inventory.models import Inventory
from inventory.serializers import InventorySerializer
@api_view(['GET','POST'])
def inventory_list(request):
"""
列出所有的code inventory,或创建一个新的inventory。
"""
if request.method == 'GET':
snippets = Inventory.objects.all()
serializer = InventorySerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = InventorySerializer(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)
项目的/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('inventory/', include('inventory.urls')),
]
应用的/urls.py
from django.urls import path
from inventory import views
app_name = 'inventory'
urlpatterns = [
path('',views.inventory_list,name='inventory_list'),
path('<str:pk>/', views.inventory_detail,name='inventory_detail'),
]
访问:http://127.0.0.1:8000/inventory/
9 请求与响应
https://q1mi.github.io/Django-REST-framework-documentation/tutorial/2-requests-and-responses_zh/
九 RESTful架构和DRF进阶
9.1 分页
在使用GET请求获取资源列表时,我们通常不会一次性的加载所有的数据,除非数据量真的很小。大多数获取资源列表的操作都支持数据分页展示,也就说我们可以通过指定页码(或类似于页码的标识)和页面大小(一次加载多少条数据)来获取不同的数据。我们可以通过对QuerySet对象的切片操作来实现分页,也可以利用Django框架封装的Paginator和Page对象来实现分页。使用DRF时,可以在Django配置文件中修改RESTFRAMEWORK并配置默认的分页类和页面大小来实现分页,如下所示。
**_settings.py**
REST_FRAMEWORK = {
# 一页十条
'PAGE_SIZE': 10,
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination'
}
效果: