django REST frameWork学习第四天序列化Serializers

新人学习django 是按照这个大佬的教程学习的
链接: https://www.cnblogs.com/derek1184405959/p/8733194.html.

很多步骤都是按照上面的教程学习的,这里只是记录一下自己学习的过程和一些错误
如果有人想要系统的学习,建议去上面那位大佬处学习

1.序列化知识
2.django的serializer序列化model
goods/view_base.py

from django.views.generic import View
from apps.goods.models import  Goods

class GoodsListView(View):
    def get(self,request):
        #通过django的view实现商品列表页
        json_list=[]
        goods=Goods.objects.all();
        #json.dumps()用于将dict类型的数据转成str,因为如果直接将dict类型的数据写入json文件中会发生报错,因此在将数据写入时需要用到该函数
        #json.loads()用于将str类型的数据转成dict。
        #json.dump()用于将dict类型的数据转成str,并写入到json文件中。下面两种方法都可以将数据写入json文件
        #json.load()用于从json文件中读取数据。
        #获取所有商品
        #for good in goods:
        #  json_dict={}
        #   #获取商品的每个字段,键值对形式
        #   json_dict["name"]=good.name
        #  json_dict["category"]=good.category.name
        #   json_dict["market_price"]=good.market_price
        #   json_list.append(json_dict)

        from django.http import HttpResponse
        import json
        from django.core import serializers
        from django.http import JsonResponse
        json_data=serializers.serialize("json",goods)
        json_data=json.loads(json_data,encoding="utf-8")
        print(json_data)
        #返回json,一定要指定类型content_type="application/json"
        #return HttpResponse(json.dumps(json_list,ensure_ascii=False),content_type="application/json")
        ##In order to allow non-dict objects to be serialized set the safe parameter to False.
        #json_dumps_params是不发送ascii码,而是原先文件,在网页中会看到的是汉字而不是ascii码
        return JsonResponse(json_data,safe=False,json_dumps_params={"ensure_ascii":False})

Mxshop/urls.py修改

 from django.contrib import admin
from django.urls import path
import xadmin
from django.urls import include
from django.views.static import serve
from MxShop.settings import MEDIA_ROOT
from apps.goods.view_base import  GoodsListView
from rest_framework.documentation import include_docs_urls

urlpatterns = [
    path('xadmin/', xadmin.site.urls),
    path('ueditor/', include('DjangoUeditor.urls')),
    path('media/<path:path>',serve,{'document_root':MEDIA_ROOT}),
    path('goods/',GoodsListView.as_view(),name="goods-list"),
    path("docs",include_docs_urls(title="alotria")),
    path("api-auth/",include("rest_framework.urls")),
]

3.APIView方式实现商品列表
1.安装
pip install coreapi drf的文档支持
pip install django-guardian drf 对象级别的权限支持

配置def的文档的url
path(“docs”,include_docs_urls(title=“alotria”)),
settings中添加

INSTALLED_APPS = [
   'rest_framework',
]

MxShop/urls.py

urlpatterns = [
    path('api-auth/',include('rest_framework.urls')),
]

goods文件夹下下面新建seralizers.py
用drf的序列化实现商品列表页展示,代码如下

from rest_framework import serializers
class GoodsSerializers(serializers.Serializer):
    name=serializers.CharField(required=True,max_length=100)
    click_num=serializers.IntegerField(default=0)
    goods_front_image=serializers.ImageField()

goods/views.py

from django.shortcuts import render

#Create your views here.
from rest_framework.views import APIView
from apps.goods.serializers import GoodsSerializers
from apps.goods.models import Goods
from rest_framework.response import  Response

class GoodsListView(APIView):
    #商品列表
    def get(self,request,format=None):
        goods=Goods.objects.all()
        goods_serialzer=GoodsSerializers(goods,many=True)
        return Response(goods_serialzer.data)

出现错误1
1.ImportError: cannot import name ‘six’ from ‘django.utils’
pip install six
然后将six.py复制到django.utils下
2.cannot import name ‘python_2_unicode_compatible’ from ‘django.utils.encoding’

找到from django.utils.encoding import python_2_unicode_compatible, smart_text

然后更改为
from django.utils.encoding import smart_text
from six import python_2_unicode_compatible

3.ModuleNotFoundError: No module named ‘django.contrib.staticfiles.templatetags’
找到’django.contrib.staticfiles.templatetags’
替换为
from django.templatetags.static import static

这里要记得将mxshop的url下导入的GoodsListView,更改成views.py的
4.drf的Modelserializer实现商品列表页
上面是用Serializer实现的,需要自己手动添加字段,如果用Modelserializer,会更加的方便,直接用__all__就可以全部序列化

#ModelSerializer实现商品列表页,直接使用__all__全部序列化
category只显示分类的id,Serialzer还可以嵌套使用,覆盖外键字段

#外键
class CategorySerializer(serializers.ModelSerializer):
    class Meta:
       model=GoodsCategory
       fields='__all__'

class GoodsSerializers(serializers.ModelSerializer):
    #覆盖外键字段
    category=CategorySerializer()
    class Meta:
       model=Goods
       fields='__all__'

5.GenericView实现商品列表页
(1)mixins和generic一起用用

GenericAPIView继承APIView,封装了很多方法,比APIView功能更强大
view.py中修改

class GoodsListView(mixins.ListModelMixin,generics.GenericAPIView):
    #商品列表
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializers
    def get(self,request,*args,**kwargs):
        return self.list(request,*args,**kwargs)

6.添加分页功能
rest_framework/settings.py源码,里面可以找到如何配置:比如认证、权限和分页等等
默认没有分页功能
项目的settings中添加

REST_FRAMEWORK = {
    #分页
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    #每页显示的个数
    'PAGE_SIZE': 10,
}

在这里插入图片描述
自定义分页 goods/view.py

  class GoodsPagination(PageNumberPagination):
    #商品列表自定义分页
    #默认每页显示的个数
    page_size = 10
    #可以动态改变显示的个数
    page_size_query_param = 'page_size'
    #页码参数
    page_query_param = 'page'
    #最多能显示多少页
    max_page_size = 100



class GoodsListView(generics.ListAPIView):
    #商品列表
    pagination_class = GoodsPagination
    queryset = Goods.objects.all()
   pagination_class = GoodsPagination

这样就不用在settings中去配置分页的参数
注意:
这里的 pagination_class = GoodsPagination
pagination_class = GoodsPagination 后面都不能添加(),不然会报错。
7.viewsets和router完成商品列表页
goods/view.py

class GoodsListViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    #'商品列表页
    #分页
    pagination_class = GoodsPagination
    #这里要定义一个默认的排序,否则会报错
    queryset = Goods.objects.all().order_by("id")
    serializer_class = GoodsSerializers

Mxshop/urls.py

router=DefaultRouter()
#配置goods的url
router.register(r"goods",GoodsListViewSet,basename="goods")

urlpatterns = [
    path('xadmin/', xadmin.site.urls),
    path('ueditor/', include('DjangoUeditor.urls')),
    path('media/<path:path>',serve,{'document_root':MEDIA_ROOT}),
    path('goods/',GoodsListView.as_view(),name='goods-list'),
    path('docs',include_docs_urls(title='alotria')),
    path('api-auth/',include('rest_framework.urls')),
    #商品列表页
    re_path('^',include(router.urls)),
]

还记得要将mxshop/urls.py中的
path(‘goods/’,GoodsListView.as_view(),name=‘goods-list’),这个字段删除掉
不需要在使用这个字段,而去使用
re_path(’^’,include(router.urls)),这个当做商品列表页
记得在这里要导入所用的类和方法

8.drf的APIView、GenericView、viewsets和router的原理分析
genericViewSet 是最高的一层

往下

GenericViewSet(viewsets) ----drf

GenericAPIView —drf

APIView —drf

View     ----django

这些view功能的不同,主要的是有mixin的存在

mixins总共有五种:

CreateModelMixin

ListModelMixin

UpdateModelMixin

RetrieveModelMixin

DestoryModelMixin

class GoodsListView(mixins.ListModelMixin,generics.GenericAPIView):
#     #商品列表
#
#     queryset = Goods.objects.all()
#     serializer_class = GoodsSerializers
#     def get(self,request,*args,**kwargs):
#         return self.list(request,*args,**kwargs)

如果不继承ListModelMixin的话,就无法将get和商品的列表关联起来,另外还有其中的分页等等,都无法实现。

还有其它几个mixin(增删改查局部),这些功能都是mixin做的

我们一般都是用viewsets

ViewSet类与View类其实几乎是相同的,但提供的是read或update这些操作,而不是get或put 等HTTP动作。同时,ViewSet为我们提供了默认的URL结构, 使得我们能更专注于API本身。

Router提供了一种简单,快速,集成的方式来定义一系列的urls

9.drf的request和response介绍

REST framework 的 Request 类扩展与标准的 HttpRequest,并做了相应的增强,比如更加灵活的请求解析(request parsing)和认证(request authentication)。

Request 解析

REST framwork 的 Request 对象提供了灵活的请求解析,允许你使用 JSON data 或 其他 media types 像通常处理表单数据一样处理请求。

.data

request.data 返回请求主题的解析内容。这跟标准的 request.POST 和 request.FILES 类似,并且还具有以下特点:

包括所有解析的内容,文件(file) 和 非文件(non-file inputs)。
支持解析 POST 以外的 HTTP method , 比如 PUT, PATCH。
更加灵活,不仅仅支持表单数据,传入同样的 JSON 数据一样可以正确解析,并且不用做额外的处理(意思是前端不管提交的是表单数据,还是 JSON 数据,.data 都能够正确解析)。
.data 具体操作,以后再说~

.query_params

request.query_params 等同于 request.GET,不过其名字更加容易理解。

为了代码更加清晰可读,推荐使用 request.query_params ,而不是 Django 中的 request.GET,这样那够让你的代码更加明显的体现出 ----- 任何 HTTP method 类型都可能包含查询参数(query parameters),而不仅仅只是 ‘GET’ 请求。

.parser

APIView 类或者 @api_view 装饰器将根据视图上设置的 parser_classes 或 settings 文件中的 DEFAULT_PARSER_CLASSES 设置来确保此属性(.parsers)自动设置为 Parser 实例列表。

通常不需要关注该属性…

如果你非要看看它里面是什么,可以打印出来看看,大概长这样:

[<rest_framework.parsers.JSONParser object at 0x7fa850202d68>, <rest_framework.parsers.FormParser object at 0x7fa850202be0>, <rest_framework.parsers.MultiPartParser object at 0x7fa850202860>]
包含三个解析器 JSONParser,FormParser,MultiPartParser。

注意: 如果客户端发送格式错误的内容,则访问 request.data 可能会引发 ParseError 。默认情况下, REST framework 的 APIView 类或者 @api_view 装饰器将捕获错误并返回 400 Bad Request 响应。 如果客户端发送的请求内容无法解析(不同于格式错误),则会引发 UnsupportedMediaType 异常,默认情况下会被捕获并返回 415 Unsupported Media Type 响应。

Responses

与基本的 HttpResponse 对象不同,TemplateResponse 对象保留了视图提供的用于计算响应的上下文的详细信息。直到需要时才会计算最终的响应输出,也就是在后面的响应过程中进行计算。 — Django 文档

REST framework 通过提供一个 Response 类来支持 HTTP 内容协商,该类允许你根据客户端请求返回不同的表现形式(如: JSON ,HTML 等)。

Response 类的子类是 Django 的 SimpleTemplateResponse。Response 对象使用数据进行初始化,数据应由 Python 对象(native Python primitives)组成。然后 REST framework 使用标准的 HTTP 内容协商来确定它应该如何渲染最终响应的内容。

当然,您也可以不使用 Response 类,直接返回常规 HttpResponse 或 StreamingHttpResponse 对象。 使用 Response 类只是提供了一个更好的交互方式,它可以返回多种格式。

除非由于某种原因需要大幅度定制 REST framework ,否则应该始终对返回 Response 对象的视图使用 APIView 类或 @api_view 装饰器。这样做可以确保视图执行内容协商,并在视图返回之前为响应选择适当的渲染器。

创建 response

Response()

与普通 HttpResponse 对象不同,您不会使用渲染的内容实例化 Response 对象。相反,您传递的是未渲染的数据,可能包含任何 Python 对象。

由于 Response 类使用的渲染器不能处理复杂的数据类型(比如 Django 的模型实例),所以需要在创建 Response 对象之前将数据序列化为基本的数据类型。

你可以使用 REST framework 的 Serializer 类来执行序列化的操作,也可以用自己的方式来序列化。

构造方法: Response(data, status=None, template_name=None, headers=None, content_type=None)

参数:

data: 响应的序列化数据。
status: 响应的状态代码。默认为200。
template_name: 选择 HTMLRenderer 时使用的模板名称。
headers: 设置 HTTP header,字典类型。
content_type: 响应的内容类型,通常渲染器会根据内容协商的结果自动设置,但有些时候需要手动指定。
属性

.data

还没有渲染,但已经序列化的响应数据。

.status_code

状态码

.content

将会返回的响应内容,必须先调用 .render() 方法,才能访问 .content 。

.template_name

只有在 response 的渲染器是 HTMLRenderer 或其他自定义模板渲染器时才需要提供。

.accepted_renderer

用于将会返回的响应内容的渲染器实例。

从视图返回响应之前由 APIView 或 @api_view 自动设置。

.accepted_media_type

内容协商阶段选择的媒体类型。

从视图返回响应之前由 APIView 或 @api_view 自动设置。

.renderer_context

将传递给渲染器的 .render() 方法的附加的上下文信息字典。

从视图返回响应之前由 APIView 或 @api_view 自动设置。

标准 HttpResponse 属性

Response 类扩展于 SimpleTemplateResponse,并且响应中也提供了所有常用的属性和方法。例如,您可以用标准方式在响应中设置 header:

response = Response()
response[‘Cache-Control’] = ‘no-cache’
.render()

与其他任何 TemplateResponse 一样,调用此方法将响应的序列化数据呈现为最终响应内容。响应内容将设置为在 accepted_renderer 实例上调用 .render(data,accepted_media_type,renderer_context) 方法的结果。

通常不需要自己调用 .render() ,因为它是由 Django 处理的。
10.drf的过滤,搜索和排序
(1)添加到app里面

INSTALLED_APPS = [
     'django_filters',
]

(2)新建filter.py

自定义一个过滤器

import django_filters
from apps.goods.models import Goods

class GoodsFilter(django_filters.rest_framework.FilterSet):
    #商品过滤的类
    #两个参数,name是要过滤的字段,lookup是执行的行为,“小于等于本店的价格”
    price_min=django_filters.NumberFilter(field_name='shop_price',lookup_expr="gte")
    price_max=django_filters.NumberFilter(field_name='shop_price',lookup_expr="lte")
    search_field=django_filters.CharFilter(field_name='name',lookup_expr='contains')
    ordering=django_filters.OrderingFilter(field_name=('sold_num','add_time'),field_labels={'sold_num':'销量','add_time':'添加时间'})

    class Meta:
        model=Goods
        fields=['price_min','price_max']

(3)views.py

class GoodsListViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    #'商品列表页
    #这里要定义一个默认的排序,否则会报错
    queryset = Goods.objects.all().order_by("id")
    # 分页
    pagination_class = GoodsPagination
    serializer_class = GoodsSerializers
    #添加要使用的功能
    filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter)
    #设置filter类为我们自定义的类
    filter_class=GoodsFilter
    #搜索,=name表示精确搜索,也可以使用正则表达式
    search_fields=('=name','goods_brief')
    #排序
    ordering_fields=('sold_num','add_time')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值