使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站

项目支持支付宝支付(暂不支持微信支付),支持手机短信验证码注册, 支持第三方登录。集成了sentry错误监控系统。

本小节内容: Django原生以及使用drf 完成 商品列表页

django的view实现商品列表页

本章节很重要。

通过Django的fbv cbv (class base view)都可以实现。

更建议通过基于class的view编码,面向对象。

实现json返回。通过商品列表页学习大多数drf知识点

  1. 配置url
商品列表页
path('goods/', GoodsListView.as_view(),name="goods-list"),
  1. 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我们不能直接调用,而应该进一步写明调用其中哪个方法。

 
mark
  1. 最基本方法问题,字段被一个一个的序列化。字段很多会很麻烦
  # 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)
  1. 如果将addtime加入会报错,json.dumps无法自己完成。
TypeError: Object of type 'add_time' is not JSON serializable

推荐阅读:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138683221577998e407bb309542d9b6a68d9276bc3dbe000

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

 
mark

安装

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行

 
mark

如果出现错误,把这个地方改为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'))
 
mark

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代替

 
mark

可以看到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)

字段太多了。我们先讲两个。

 
mark

因为我们是在用浏览器请求所以Drf会帮你渲染成网页格式

 
mark

这就是drf的Web browsable API

使用浏览器请求会返回html。

 
mark

get的时候指明json

 
mark
 
mark

接口的描述我们可以自行定义。

post过去的数据他能解析的格式。

因为我们是序列化的Goods,所以我们的Serializer要和goods model中保持一致

我们在Serializer中加上front image

 
mark

可以看到我们返回的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__"
 
mark

外键会序列化成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

 
mark

这些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配置

 
mark

可以看到已经不提供默认的分页类了。我们需要自己指明

REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10,
}
 
mark
 
mark

返回的数据有了变化。

有了count next页的url,将之前的数据放到了results中

 
mark

很神奇的是图片连域名都加上了。

问题来了: 这个域名怎么加上的,待探究。

将整个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
 
mark

第几页,每一页取多少条都变成了可配置的。

Viewsets和router完成商品列表页

from rest_framework import viewsets
 
mark

可以看到它里面包含的

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):

它的内部之间pass,只是多继承了一个ViewSetMixin

ViewSetMixin中重写了as_view方法可以让我们的注册url变得更加简单

 
mark

在view的基础上设置了很多动作。动态设置Serializer

class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):

GenericViewSet只继承了api view,那么原来ListAPIView中的get方法的实现就没有了

class GoodsListView(mixins.ListModelMixin, viewsets.GenericViewSet):

ViewSets和Routers配套使用。

  1. 为了让我们更好看清我们使用的是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。
以及这些关系的组合使用,这样才能让我们更清楚什么时候使用哪种。

  1. genericViewSet 是最高的一层
GenericViewSet(ViewSet) -drf
GenericAPIView -drf
APIView -drf
View -django

这些view之间的差异就引出了drf中另一个核心点mixin

 
mark

可以看到源码中的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就能组合出更加强大的:

 
mark

如上图这些分别为某个单独操作设置的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时有很大好处。

 
mark

文章学习来自简书 作者:天涯明月笙
原文链接:https://www.jianshu.com/p/6a6fa62d8152

5- vue django restful framework 打造生鲜超市 -完成商品列表页(上)的更多相关文章

  1. 6- vue django restful framework 打造生鲜超市 -完成商品列表页(下)

    Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页下 drf中的request和response drf对于django的 ...

  2. 4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍

    4- vue django restful framework 打造生鲜超市 -restful api 与前端源码介绍 天涯明月笙 关注 2018.02.20 19:23* 字数 762 阅读 135 ...

  3. 3- vue django restful framework 打造生鲜超市 - model设计和资源导入

    3- vue django restful framework 打造生鲜超市 - model设计和资源导入 使用Python3.6与Django2.0.2(Django-rest-framework) ...

  4. 7- vue django restful framework 打造生鲜超市 -商品类别数据展示(上)

    Vue+Django REST framework实战 搭建一个前后端分离的生鲜超市网站 Django rtf 完成 商品列表页 并没有将列表页的数据json 与前端的页面展示结合起来 讲解如果将dr ...

  5. 1- vue django restful framework 打造生鲜超市

    Vue+Django REST framework实战 使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支 ...

  6. 2- vue django restful framework 打造生鲜超市 -环境搭建

    使用Python3.6与Django2.0.2(Django-rest-framework)以及前端vue开发的前后端分离的商城网站 项目支持支付宝支付(暂不支持微信支付),支持手机短信验证码注册, ...

  7. 引爆潮流技术 Vue+Django REST framework打造生鲜电商项目

    引爆潮流技术Vue+Django REST framework打造生鲜电商项目 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感受, ...

  8. Vue+Django REST framework打造生鲜电商项目

    1-1 课程导学 2-1 Pycharm的安装和简单使用 2-2 MySQL和Navicat的安装和使用 2-3 Windows和Linux下安装Python2和Python3 2-4 虚拟环境的安装 ...

  9. web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 ☝☝☝

    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程    web前端Vue+Django rest framework 框架 生鲜电商项目实战视频教程 学习 ...

随机推荐

  1. @Modifying 注解完成修改操作

    以上我们做的都是查询,那要如何实现 修改.删除和添加呢? 可以通过以下两种方式: (1)通过实现 CrudRepository 接口来完成(以后介绍): (2)通过 @Modifying 注解完成修改 ...

  2. 练习四十六:列表排序,删除list中重复的元素

    方法一:使用集合set;将list直接转换为set a = [1,3,4,3,5,7] a = list(set(a)) print(a) 执行结果: [1, 3, 4, 5, 7] 方法二:直接排序 ...

  3. web 中防止sql注入

    public class SqlInject:Page { //检测到注入后的处理方式: 0:仅警告:1:警告+记录:2:警告+自定义错误页面:3:警告+记录+自定义错误页面 ; private co ...

  4. DEDE修改注册邮箱时一起修改UCenter中用户邮箱的问题

    最近在做一个项目,就是在账号安全栏目中加一个修改邮箱并验证的功能,这个功能并不复杂,可以参照用户注册时的邮箱验证来实现. 就是当用户更改邮箱并提交之后,发一封包含一个链接的邮件到用户的新邮箱中,当用户 ...

  5. Dedecms标签arclistsg调用单表模型出错的解决方法

    使用arclistsg标签调用分类信息等单表模型出错提示Column 'id' in where clause is ambiguous,  修改文件:include\taglib\arclistsg ...

  6. 《疯狂动物城》主题曲《TryEverything》中文翻译

    <疯狂动物城>主题曲<TryEverything>夏奇拉激情献唱,很多事情是需要是试试,不试试就不知道可以成功. Oh oh oh oh oooh 哦哦哦哦哦 Oh oh oh ...

  7. WPF自定义分页控件,样式自定义,简单易用

    WPF自定义分页控件 做了许久伸手党,终于有机会贡献一波,搜索一下WPF分页控件,还是多,但是不太通用,主要就是样式问题,这个WPF很好解决,还有一个就是分页控件嘛,只关心几个数字的变动就行了,把页码 ...

  8. json解析数组类型的数据

    //微信里一个检测是否有发送模版消息的权限的方法//此处的openid代表的微信用户openid,templateId代表的是模版消息idpublic boolean checkIsSendTempM ...

  9. 解决ARCGIS10.2与VS2013不兼容

    在注册表中HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0增加类型为REG_SZ的InstallDir节点.Ins ...

  10. spring ehcache 使用详解

    Spring 整合 Ehcache 管理缓存详解  yellowbutterfly 前言 Ehcache 是一个成熟的缓存框架,你可以直接使用它来管理你的缓存. Spring 提供了对缓存功能的抽象: ...