拿之前的过来用:
from rest_framework import serializers
from goods.models import GoodsInfo
# 定义一些序列号程序
class GoodsInfoSerializer(serializers.ModelSerializer):
# 创建序列化器
class Meta:
# 定义元类
# model指明了当前的序列化器和哪个模型产生联系
model = GoodsInfo
fields = '__all__' # 意思是所有的字段都要
# 这样写是自己选择需要的字段
# fields = ('url', 'username', 'email', 'groups')
除了之前两中设置字段对应之外还有第三种:
exclude设置为要从序列化程序中排除的字段列表。
# 不需要写fields
model = GoodsInfo
exclude = ('is_delete',) # 意思是除了这个字段都包含
用于有外键的数据库,设置depth为整数,通常为1
from user.models import UserInfo
from rest_framework import serializers
class UserAutoSerializers(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = '__all__'
depth = 1
用shell调试结果为:
>>> from user.serializers import *
>>> ser = UserAutoSerializers()
>>> ser
UserAutoSerializers():
id = IntegerField(label='ID', read_only=True)
name = CharField(max_length=20)
password = CharField(max_length=20, required=False)
phone = CharField(max_length=11)
addkey = NestedSerializer(read_only=True):
id = IntegerField(label='ID', read_only=True)
add = CharField(max_length=50)
>>>
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
groups = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
model = Account
想要指定readonly字段还有第二个Meta选项,read_only_fields.:
read_only_fields = ('account_name',)
还有一个快捷方式,允许您在字段上指定任意附加关键字参数,使用extra_kwargs选择。如在.的情况下read_only_fields,这意味着不需要显式声明序列化程序上的字段。
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
就是HttpRequest的扩展功能
.data:
request.data返回请求主体的解析内容(可以解析各种类型请求包括POST等)。这与标准类似。request.POST和request.FILES属性除外:
.query_params:
相当于request.GET,但是任何HTTP方法类型都可能包含查询参数,而不仅仅是GET请求
数据类型可以是str,list,dict等
class Response(SimpleTemplateResponse):
"""
An HttpResponse that allows its data to be rendered into
arbitrary media types.
"""
def __init__(self, data=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None):
data:为响应准备的序列化之后的数据,status是状态码,template_name模板的名称
headers:响应头信息,content_type:一般不需要指定,框架根据前端传递的信息来指定
还是推荐看官网:https://www.django-rest-framework.org/api-guide/views/
集成于Django的view类,和view不同地方在于:
class APIView(View):
# The following policies may be set at either globally, or per-view.
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
parser_classes = api_settings.DEFAULT_PARSER_CLASSES
# 身份认证
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
metadata_class = api_settings.DEFAULT_METADATA_CLASS
versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from goods.serializers import *
class ListGoodsView(APIView):
# 可以不需要验证
# authentication_classes = (authentication.TokenAuthentication, )
# permission_classes = (permissions.IsAdminUser, )
def get(self, request, format=None):
goods = [good.name for good in GoodsInfo.objects.all()]
# 多条数据要写many=True
data = GoodsInfo.objects.all()
ser = GoodsInfoNewSerializer(data, many=True)
return Response(ser.data)
def post(self, request):
# 反序列化需要data=
ser = GoodsInfoNewSerializer(data=request.data)
# 需要验证
ser.is_valid()
print(ser.validated_data)
ser.save()
return Response(ser.validated_data)
这个是对APIView的再次封装,实现更强和更简洁的功能,通常还会和mixins联合使用:
1.ListModelMixin
列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。
该Mixin的list方法会对数据进行过滤和分页。
2.CreateModelMixin
创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
如果序列化器对前端发送的数据验证失败,返回400错误。
3.RetrieveModelMixin
详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
如果存在,返回200, 否则返回404。
4.UpdateModelMixin
更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
成功返回200,序列化器校验数据失败时,返回400错误。
5.DestroyModelMixin
删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
成功返回204,不存在返回404。
mixins的子类中会带有对应可以使用的方法,看上文,这时候要写queryset和serializer_class以及对应的请求方式,并返回mixins子类中的方法
from goods.serializers import *
from rest_framework.mixins import *
from rest_framework.generics import *
class GenericsView(GenericAPIView, ListModelMixin):
queryset = GoodsInfo.objects.all()
serializer_class = GoodsInfoNewSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
如果直接使用下文的子类更简单:
意思是自动调用post方法,不需要再自己调用这个方法
from goods.serializers import *
from rest_framework.generics import *
class CreateGoodsView(CreateAPIView):
# queryset = GoodsInfo.objects.all() # 创建的时候可以不用设置数据库内容
serializer_class = GoodsInfoNewSerializer
使用已有的子类代表GenericAPIView和mixins的混合使用
几个子类视图
1) CreateAPIView
提供 post 方法
继承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
继承自:GenericAPIView、ListModelMixin
3)RetireveAPIView
提供 get 方法
继承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法
继承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法
继承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
提供 get、put、patch方法
继承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
视图集ViewSet,使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中。使用ViewSet时不需要再views.py里写get->return list这种类型的,只需要在urls.py里写对应逻辑:
views.py内容:自己导包,写了GenericViewSet,ModelViewSet,ViewSet
class MyViewSet(GenericViewSet, ListModelMixin):
queryset = GoodsInfo.objects.filter(id__gt=15)
serializer_class = GoodsInfoNewSerializer
class GoodsInfoView(ModelViewSet):
# 先导包ModelViewSet和数据库Model和serializers下的类
# queryset是一个查询集,存储所有的数据库查询之后的数据,是一个属性不能修改名字
queryset = GoodsInfo.objects.all()
'''serializer_class用来指定再当前的视图立面进行序列化和反序列化时
使用的序列化器(也叫串行器)'''
serializer_class = GoodsInfoNewSerializer
class UserViewSet(ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
urls.py内容,两种方式,router是自动完成绑定:
from django.conf.urls import url, include
from goods.views import *
from rest_framework.routers import DefaultRouter
# 定义视图处理的路由器
router = DefaultRouter()
# 在路由器中注册视图集
router.register('showgoods', GoodsInfoView, base_name='hello')
router.register('viewset', MyViewSet, base_name='viewset')
urlpatterns = [
url(r'', include(router.urls)),
url(r'^goodslist/$', ListGoodsView.as_view()),
url(r'^show/$', GenericsView.as_view()),
url(r'^(?P\d+)+(/showgoods/)$' , GoodsInfoView.as_view({'get':'retrieve','post':'create','put':'update'})),
]
或者这样写之一:
viewset = MyViewSet.as_view({
'get': 'list',
})
# 商品列表页
url('viewset/', goods_list,name="viewset"),
这样区别并写自己的特殊方法:
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
1) ViewSet
继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。
在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。
2)GenericViewSet
继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。
添加自定义动作需要使用rest_framework.decorators.action装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
methods: 该action支持的请求方式,列表传递
detail: 表示是action中要处理的是否是视图资源的对象(即是否通过url路径获取主键)
True 表示使用通过URL获取的主键对应的数据对象
False 表示不使用URL获取主键
实例:
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
# detail为False 表示不需要处理具体的BookInfo对象
@action(methods=['get'], detail=False)
def latest(self, request):
"""
返回最新的图书信息
"""
book = BookInfo.objects.latest('id')
serializer = self.get_serializer(book)
return Response(serializer.data)
# detail为True,表示要处理具体与pk主键对应的BookInfo对象
@action(methods=['put'], detail=True)
def read(self, request, pk):
"""
修改图书的阅读量数据
"""
book = self.get_object()
book.bread = request.data.get('read')
book.save()
serializer = self.get_serializer(book)
return Response(serializer.data)
urls.py的跳转逻辑:
urlpatterns = [
url(r'^books/$', views.BookInfoViewSet.as_view({'get': 'list'})),
url(r'^books/latest/$', views.BookInfoViewSet.as_view({'get': 'latest'})),
url(r'^books/(?P\d+)/$' , views.BookInfoViewSet.as_view({'get': 'retrieve'})),
url(r'^books/(?P\d+)/read/$' , views.BookInfoViewSet.as_view({'put': 'read'})),
]
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass