5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)
使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站
项目支持支付宝支付(暂不支持微信支付),支持手机短信验证码注册, 支持第三方登录。集成了sentry错误监控系统。
本小节内容: Django原生以及使用drf 完成 商品列表页
django的view实现商品列表页
本章节很重要。
通过Django的fbv cbv (class base view)都可以实现。
更建议通过基于class的view编码,面向对象。
实现json返回。通过商品列表页学习大多数drf知识点
- 配置url
商品列表页
path('goods/', GoodsListView.as_view(),name="goods-list"),
- goods中新建一个view_base 来实现一个只通过Django实现的json返回。
查看Django的开发文档可以看到提供了很多view来减少我们的代码量
class GoodsListView(View):
def get(self, request):
"""
通过django的view实现商品列表页
"""
json_list = []
goods = Goods.objects.all()[:10]
from django.forms.models import model_to_dict
for good in goods:
json_dict = model_to_dict(good)
json_list.append(json_dict)
import json
from django.core import serializers
json_data = serializers.serialize('json', goods)
json_data = json.loads(json_data)
from django.http import HttpResponse, JsonResponse
return JsonResponse(json_data, safe=False)
model_to_dict 将model转换为字典,不用一个字段一个字段提取。
- images field和 datetime直接dumps会出错
- serializers 专门用于序列化,有了这个序列化,其实上面的model_to_dict都不用做了
moudle not callable
说明这是一个moudle我们不能直接调用,而应该进一步写明调用其中哪个方法。
- 最基本方法问题,字段被一个一个的序列化。字段很多会很麻烦
# 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_dict["add_time"] = good.add_time
# json_list.append(json_dict)
- 如果将addtime加入会报错,json.dumps无法自己完成。
TypeError: Object of type 'add_time' is not JSON serializable
推荐阅读:
Django本身的实现其实已经蛮简单了,那我们为啥要用drf
敲重点!!!
images这个图片保存的是一个相对路径,而我们需要加上前面的前缀。
这个工作drf可以完成补前缀工作。
字段序列化方式被定死了,重组麻烦。
文档生成,输入检测(你是放在request body还表单过来的)
使用drf完成商品列表页
商品列表页过基础知识
http://www.django-rest-framework.org/
强大的,灵活的,api
- Web browsable API
- Authentication policies 认证
- Serialization that supports both ORM and non-ORM data sources.
序列化ORM 和 非ORM的数据源
regular function-based views 我们是用的cbv
安装
coreapi (1.32.0+) - Schema generation support.
django-guardian (1.1.1+) - Object level permissions support.
对象级别的权限支持,coreapi支持文档
安装时报出utf-8 decode错误
修改虚拟环境中的
D:\CodeSpace\PythonEnvs\mxshop36\Lib\site-packages\pip\compat
大约75行
如果出现错误,把这个地方改为gbk
引入我们的文档。
# 自动化文档,1.11版本中注意此处前往不要加$符号
path('docs/', include_docs_urls(title='mtianyan生鲜超市文档'))
配置好了只要运行不报错验证成功。
Add 'rest_framework' to your INSTALLED_APPS setting.
INSTALLED_APPS = (
...
'rest_framework',
)
path('api-auth/', include('rest_framework.urls'))
http://www.django-rest-framework.org/tutorial/3-class-based-views/
这里面官方给出了一个例子如何简单的写一个class view
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
将官方示例中的snippets用我们的Goods代替
可以看到api view也是继承的view在它之上做了很多事。
from .models import Goods
写明引入当前目录下models中的Goos不容易重名失败。
可以自定义序列化的类。SnippetSerializer
modelform 和 form。modelform可以将字段直接转成html
现在drf里的Serializer是用来取代form开发的。modelfrom是针对html的,
Serializer是针对json的。
和之前的form一样。新建一个文件serializers.py
http://www.django-rest-framework.org/tutorial/1-serialization/
from rest_framework import serializers
class GoodsSerializer(serializers.Serializer):
name = serializers.CharField(required=True,max_length=100)
click_num = serializers.IntegerField(default=0)
字段太多了。我们先讲两个。
因为我们是在用浏览器请求所以Drf会帮你渲染成网页格式
这就是drf的Web browsable API
使用浏览器请求会返回html。
get的时候指明json
接口的描述我们可以自行定义。
post过去的数据他能解析的格式。
因为我们是序列化的Goods,所以我们的Serializer要和goods model中保持一致
我们在Serializer中加上front image
可以看到我们返回的json中,image字段全部加上了media前缀
前缀是通过我们setting的MEDIA_URL 来自动添加的。
drf的modelSerializer实现商品列表页功能
在drf的登录系统中user nonetype
注意检查这里需要返回的是username
def __str__(self):
return self.username
之所以可以登录退出,
是因为这里配置了一个url
# 调试登录
path('api-auth/', include('rest_framework.urls'))
goods/views.py添加:
def post(self, request, format=None):
serializer = GoodsSerializer(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)
接收前端request数据,交给GoodsSerializer进行验证,验证通过进行保存。
goods/serializers.py添加:
def create(self, validated_data):
"""
Create and return a new `Goods` instance, given the validated data.
"""
return Goods.objects.create(**validated_data)
有了drf之后,他会把不管是用户GET post Body过来的数据
都会取到,放到data中。不需要对于get post 等做单独的处理。
save 会去调用Serializer里的create方法。
Django有form和modelform。那么Serializer是不是也有他的model
bingo
class GoodsSerializer(serializers.ModelSerializer):
class Meta:
model = Goods
# fields = ('category', 'goods_sn', 'name', 'click_num', 'sold_num', 'market_price')
fields = "__all__"
外键会序列化成id。那我们通过id拿到对应的category
进行Serializer的嵌套使用。覆盖外键字段
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
fields = "__all__"
class GoodsSerializer(serializers.ModelSerializer):
category = CategorySerializer()
class Meta:
model = Goods
# fields = ('category', 'goods_sn', 'name', 'click_num', 'sold_num', 'market_price')
fields = "__all__"
GenericView 方式实现商品列表页和分页功能
使用更加上层的view写起来更简单。
使用Using mixins 和 generic view
GenericAPIView是在apiview的基础上加了filter 分页等一堆东西
我们不用添加createModelMixin是因为我们的商品数据是后台添加的,前台不会提交。
class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
"""
商品列表页
"""
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
list函数是在mixin中的,做了分页以及序列化。
不去重写定义get等http请求的方法默认你不接收这种方法
虽然上面已经很简单了,但是我们能不能更简单呢。
查看源码路径: D:/CodeSpace/PythonEnvs/mxshop36/Lib/site-packages/rest_framework
D:/CodeSpace/PythonEnvs/mxshop36/Lib/site-packages/rest_framework/generics.py
这些view都是官方提供给我们的view
- ListAPIview (获取列表)
- CreateAPiView (创建一个)
- Retrieve (获取某一条)
class GoodsListView(ListAPIView):
"""
商品列表页
"""
queryset = Goods.objects.all()
serializer_class = GoodsSerializer
列表页通常都是要分页的,我们如何只通过setting的一个配置完成我们的分页。
所有关于restframework的配置要写在变量里
D:/CodeSpace/PythonEnvs/mxshop36/Lib/site-packages/rest_framework/settings.py
源码中的setting配置
可以看到已经不提供默认的分页类了。我们需要自己指明
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10,
}
返回的数据有了变化。
有了count next页的url,将之前的数据放到了results中
很神奇的是图片连域名都加上了。
问题来了: 这个域名怎么加上的,待探究。
将整个url提供实际是我们restful api的一个标准
class GoodsPagination(PageNumberPagination):
page_size = 12
page_size_query_param = 'page_size'
page_query_param = "page"
max_page_size = 100
最多100个。
goodslistview中添加
pagination_class = GoodsPagination
第几页,每一页取多少条都变成了可配置的。
Viewsets和router完成商品列表页
from rest_framework import viewsets
可以看到它里面包含的
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
它的内部之间pass,只是多继承了一个ViewSetMixin
ViewSetMixin中重写了as_view方法可以让我们的注册url变得更加简单
在view的基础上设置了很多动作。动态设置Serializer
class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
GenericViewSet只继承了api view,那么原来ListAPIView
中的get方法的实现就没有了
class GoodsListView(mixins.ListModelMixin, viewsets.GenericViewSet):
ViewSets和Routers配套使用。
- 为了让我们更好看清我们使用的是viewset的实现.
goods/views.py
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
改名字
配置我们的url
goods_list = GoodsListViewSet.as_view({
'get': 'list',
})
将get请求绑定到list之上,类似于之前的
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
这样我们就不用自己再去绑定了。
配置url时就不用再加as_view()了
# 商品列表页
path('goods/', goods_list,name="goods-list"),
但是我们可以更厉害一点,直接不用进行这个get 与list的绑定,它自动完成
我们要介绍的router就是做这个的。
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
# 配置goods的url
router.register(r'goods', GoodsListViewSet)
url中配置
# router的path路径
re_path('^', include(router.urls)),
router自动帮我们配置了get 和list,create 和 post的绑定
对于api view, GenericView viewset 和 router 的原理分析
理清我们的这些view他们之间的关系,以及listmodelMixin。
以及这些关系的组合使用,这样才能让我们更清楚什么时候使用哪种。
- genericViewSet 是最高的一层
GenericViewSet(ViewSet) -drf
GenericAPIView -drf
APIView -drf
View -django
这些view之间的差异就引出了drf中另一个核心点mixin
可以看到源码中的mixin一共有五种
而各种view的差异,mixin就扮演着重要的角色
以ListModelMixin为例做区别,如果我们不去继承这个mixin它里面的这些方法的话。
就无法将get 和 list连接起来。无法连接,那么list中所作的所有功能都不能完成。
比如其中的
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
过滤,分页都将享受不到。
RetrieveModelMixin对于具体的商品信息进行了获取,序列化。这个在后面的商品详情页会介绍到。
UpdateModelMixin中对于部分更新还是全部更新进行了判断。
DestroyModelMixin用来连接我们的delete方法,在我们delete时有一些必要的操作,如设置返回状态204等。
上述这些功能都是mixin做的,而generic view并没有做。所以drf是通过两者的结合来实现。
GenericAPIView继承于views.APIView
Base class for all other generic views.是所有通用视图的基类
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
在原本的apiview基础上添加了过滤,分页。如果不用genericapiview而用api view这些事情都要我们自己实现。
配合着genericview 加上mixin就能组合出更加强大的:
如上图这些分别为某个单独操作设置的apiview
class RetrieveAPIView(mixins.RetrieveModelMixin,
GenericAPIView):
"""
Concrete view for retrieving a model instance.
具体的视图 对于 检索一个model实例
"""
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
get响应的是浏览器发过来的请求,浏览器发过来的请求只有http协议中规定的几种。
我们将get请求绑定上retrieve方法,就能享受到retrieve方法给我们的好处
我们可以自己写一个view来继承mixins.RetrieveModelMixin,GenericAPIView 但是我们
一定要把get 和 retrieve的绑定写上。
一般我们都会优先考虑下面组合好的这些apiview。还是满足不了要求,那就自己组合,满足这种配置方式就可以了。
Viewset有哪些好处?
generic下的各种变种view也是继承了genericAPIView,配合各种mixin进行组合工作。
它将具体的单个modelmixin(如:mixins.RetrieveModelMixin,)换成了ViewSetMixin
之前我们需要写函数将get等与retrieve等进行绑定。
ViewSetMixin的好处就是: 不需要我们通过方法来绑定。但是我们还是需要绑定关系的。
在url配置的时候进行绑定。
def as_view(cls, actions=None, **initkwargs)
他重写了as_view,接受参数,传递到对应的method 与 action进行绑定
goods_list = GoodsListViewSet.as_view({
'get': 'list',
})
将本来在代码中的绑定移到url中进行一个绑定的配置。
我们可以用router进行一个默认的绑定,router中的绑定其实和generic中的差不多
viewSetmixin还有一个很大的功能:
def initialize_request(self, request, *args, **kwargs):
"""
Set the `.action` attribute on the view,
depending on the request method.
"""
request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs)
method = request.method.lower()
if method == 'options':
# This is a special case as we always provide handling for the
# options method in the base `View` class.
# Unlike the other explicitly defined actions, 'metadata' is implicit.
self.action = 'metadata'
else:
self.action = self.action_map.get(method)
return request
为视图绑定动作,依赖于具体的request请求方法。这些action在我们后期进行动态Serializer时有很大好处。
文章学习来自简书 作者:天涯明月笙
原文链接:https://www.jianshu.com/p/6a6fa62d8152
5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)的更多相关文章
- 6- vue django restful framework 打造生鲜超市 -完成商品列表页(下)
Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页下 drf中的request和response drf对于django的 ...
- 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍
4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍 天涯明月笙 关注 2018.02.20 19:23* 字数 762 阅读 135 ...
- 3- vue django restful framework 打造生鲜超市 - model设计和资源导入
3- vue django restful framework 打造生鲜超市 - model设计和资源导入 使用Python3.6与Django2.0.2(Django-rest-framework) ...
- 7- vue django restful framework 打造生鲜超市 -商品类别数据展示(上)
Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页 并没有将列表页的数据json 与前端的页面展示结合起来 讲解如果将dr ...
- 1- vue django restful framework 打造生鲜超市
Vue+Django REST framework实战 使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支 ...
- 2- vue django restful framework 打造生鲜超市 -环境搭建
使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支付宝支付(暂不支持微信支付),支持手机短信验证码注册, ...
- 引爆潮流技术 Vue+Django REST framework打造生鲜电商项目
引爆潮流技术Vue+Django REST framework打造生鲜电商项目 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受, ...
- Vue+Django REST framework打造生鲜电商项目
1-1 课程导学 2-1 Pycharm的安装和简单使用 2-2 MySQL和Navicat的安装和使用 2-3 Windows和Linux下安装Python2和Python3 2-4 虚拟环境的安装 ...
- web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝
web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...
随机推荐
- Lecture--9 Sorting
1/排序算法:冒泡排序bubble sort,插入排序 insertion sort,选择排序 selection sort,快速排序 quick sort,归并排序 merge sort;堆排序 h ...
- Oracle11G的用户解锁、卸载以及基础操作
Oracle用户解锁 [以下操作,必须以超级管理员身份登录,才能修改]oracle安装后,会默认生成很多个用户 以超级管理员身份登录,请注意,其中的空格符:[ sys是一个超级管理员,有最大的权限,d ...
- 《C#高效编程》读书笔记12-使用推荐成员初始化器而不是赋值语句
通常来说类都有不止一个构造函数.随着时间推移,成员变量的增加,构造函数的个数也会不断的增加.预防这种情况的最好方法是,在声明变量的时候就进行初始化,而不是在每个构造函数中进行. //初始化变量时声明 ...
- 面试(Java之IO与NIO)
一.概念 NIO即New IO,这个库是在JDK1.4中才引入的.NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多.在Java API中提供了两套N ...
- 解决WinSCP连接虚拟机
其实虚拟机你也可以将它形象化,认为它就是一台电脑,只是这个电脑在你的内存中,所以,一般电脑所具有的的功能虚拟机一样拥有,它也可以当成一台独立的个体哦. 针对很多使用WinSCP连接不上虚拟机的问题,这 ...
- Windows系统HTTP身份验证方法
当Windows客户端尝试使用HTTP协议访问基于Web的资源时,会在客户端和服务器之间建立"对话".换句话说,服务器告诉客户端,访问资源之前进行身份验证 ,并且服务器还告诉客户端 ...
- linux服务器免密钥登录
方法一:通过下载服务器私钥方式 服务器端执行: ssh-keygen -t rsa -b 4096 cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys ...
- jQuery-显示与隐藏不用判断的快捷方法
功能:显示被隐藏的元素,隐藏已显示的元素. 常规方法:(需要先判断元素状态) $("button").click(function(){ if ($(".content& ...
- String和string
String和string的区别 从位置讲: 1.String是.NET Framework里面的String,小写的string是C#语言中的string 2.如果把using ...
- mybatis-关联关系2
关系关系主要有一对一,一对多,多对多,往往多对多都是通过俩个一对多来完成的 实例项目还是之前的,只是增加了一个年级实体类 1.创建年级实体类:---年级中有学生的集合 package com.java ...