Django+Vue开发生鲜电商平台之5.使用DRF实现商品列表页和过滤(中)

简介: 先了解Django中实现Json数据传递的基本方法,可以查看中文文档

2.使用modelserializer实现商品序列化

从前面的基本使用中可以看到,serializer类似于Django自带的Form,可以对表单进行验证,但是serializer还拥有更多的功能,这里尝试通过serializer将数据保存到数据库中。

在serializers.py中实现用于保存数据的create()方法如下:

from rest_framework import serializers
from .models import Goods
class GoodsSerializer(serializers.Serializer):
    name = serializers.CharField(required=True, max_length=300)
    click_num = serializers.IntegerField(default=0)
    goods_front_image = serializers.ImageField()
    def create(self, validated_data):
        '''接受前端的数据并保存'''
        return Goods.objects.create(**validated_data)

views.py中实现用于提交数据的post方法如下:

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Goods
from .serializers import GoodsSerializer
# Create your views here.
class GoodsListView(APIView):
    '''商品序列化'''
    def get(self, request, format=None):
        goods = Goods.objects.all()[:10]
        goods_serializer = GoodsSerializer(goods, many=True)
        return Response(goods_serializer.data)
    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)

当然,添加商品数据一般是后台管理员的操作,前台用户是没有这个权限的。

Django中有Form,也有ModelForm,DRF中也有ModelSerializer,相比于Serializer,它省去了模型所有字段的添加和处理数据方法的实现,serializers.py简化如下:

from rest_framework import serializers
from .models import Goods
class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = ['category', 'name', 'sold_num', 'shop_price', 'goods_brief', 'goods_front_image', 'is_hot']

由ModelSerializer自动完成与模型中相应字段的映射,显然,简洁很多,此时再访问http://127.0.0.1:8000/goods/如下:

2345_image_file_copy_5.jpg

显然,此时将指定字段返回前端,还可以指定fields = '__all__'来序列化所有字段,如下:

from rest_framework import serializers
from .models import Goods
class GoodsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Goods
        fields = '__all__'

再次访问,显示:

2345_image_file_copy_6.jpg

显然,序列化了所有字段,并且没有出错。

此时对于商品信息,category显示的时对应GoodsCategory模型的主键,当然还可以显示Category的具体信息,此时需要使用嵌套序列化,如下:

from rest_framework import serializers
from .models import Goods, GoodsCategory
class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = '__all__'
class GoodsSerializer(serializers.ModelSerializer):
    category = CategorySerializer()
    class Meta:
        model = Goods
        fields = '__all__'

即用自定义字段覆盖原有的category字段,显示如下:

2345_image_file_copy_7.jpg

此时已经显示出category的具体信息。

3.GenericView方式实现商品列表页和分页

现在进一步使用mixinsGenericView让代码更加简洁。

views.py如下:

from rest_framework import mixins, generics
from rest_framework.response import Response
from .models import Goods
from .serializers import GoodsSerializer
# Create your views here.
class GoodsListView(mixins.ListModelMixin, generics.GenericAPIView):
    '''商品列表页'''
    queryset = Goods.objects.all()[:10]
    serializer_class = GoodsSerializer
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

访问http://127.0.0.1:8000/goods/,具有与之前一样的效果,代码还可以进一步简化:

from rest_framework import mixins, generics
from rest_framework.response import Response
from .models import Goods
from .serializers import GoodsSerializer
# Create your views here.
class GoodsListView(generics.ListAPIView):
    '''商品列表页'''
    queryset = Goods.objects.all()[:10]
    serializer_class = GoodsSerializer

还可以进行分页,只需要在settings.py中进行配置即可:

# DRF配置
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}

显示:

image.jpeg

显然,此时已经实现分页的效果,并且比之前现实的信息更多,包括了总数、当前页的上一页、下一页等信息,并且图片地址也添加了域名、成为可访问的完整路径。

除了使用默认分页,还可以进行个性化定制,views.py如下

from rest_framework import generics
from rest_framework.pagination import PageNumberPagination
from .models import Goods
from .serializers import GoodsSerializer
# Create your views here.
class GoodsPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    page_query_param = 'p'
    max_page_size = 100
class GoodsListView(generics.ListAPIView):
    '''商品列表页'''
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

此时可以注释掉settings.py中关于REST_FRAMEWORK的配置,再次访问如下:

image.jpeg

此时表示页数的参数变为了指定的p,并且可以指定page_size参数,超过范围会提示页面无效。

4.viewsets和router实现商品列表页

viewsets中含有很多常见的视图,可以让代码变得更加简洁高效。

使用GenericViewSet如下:

from rest_framework import mixins, viewsets
from rest_framework.pagination import PageNumberPagination
from .models import Goods
from .serializers import GoodsSerializer
# Create your views here.
class GoodsPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    page_query_param = 'p'
    max_page_size = 100
class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    '''商品列表页'''
    queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

urls.py进行路由配置如下:

from django.conf.urls import url, include
from django.views.static import serve
from rest_framework.documentation import include_docs_urls
import xadmin
from .settings import MEDIA_ROOT
from goods.views import GoodsListViewSet
goods_list = GoodsListViewSet.as_view({
    'get': 'list',
})
urlpatterns = [
       url(r'^xadmin/', xadmin.site.urls),
       url(r'^media/(?P<path>.*)$', serve, {'document_root':MEDIA_ROOT}),
       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
       # 商品列表页
       url(r'goods/$', goods_list, name='goods-list'),
       # 文档路由
       url(r'docs/', include_docs_urls(title='生鲜电商'))
]

使get()请求绑定到list()方法,此时访问http://127.0.0.1:8000/goods/效果与之前相同,还可以使用router自动完成配置进一步简化,urls.py如下:

from django.conf.urls import url, include
from django.views.static import serve
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter
import xadmin
from .settings import MEDIA_ROOT
from goods.views import GoodsListViewSet
# Create a router and register our viewsets with it.
router = DefaultRouter()
# 配置goods的路由
router.register(r'goods', GoodsListViewSet)
urlpatterns = [
       url(r'^xadmin/', xadmin.site.urls),
       url(r'^media/(?P<path>.*)$', serve, {'document_root':MEDIA_ROOT}),
       url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
       # 商品列表页
       url(r'^', include(router.urls)),
       # 文档路由
       url(r'docs/', include_docs_urls(title='生鲜电商'))
]

router执行rigister()方法会自动进行配置,将get()请求转到list()方法、post()请求转到create()方法,还执行一些其他默认操作,以后添加其他模型的视图也直接添加一行代码router.register(r'xxx', XxxListViewSet)即可。

访问效果与之前相同。

5.各种View的分析

前面用到过不同的View来实现商品列表页,现在结合源码进一步分析。

GenericViewSet(viewsets)是最高一层的View,继承自GenericAPIView,而GenericAPIView又继承自APIView,APIView又继承自View,前3个均属于DRF,View属于Django。

它们的主要差异在于mixins,包括CreateModelMixin、ListModelMixin、RetrieveModelMixin、UpdateModelMixin和DestroyModelMixin等,ListModelMixin中含有list()方法。

GenericAPIView继承自APIView,在APIView的基础上实现过滤、分页等功能;

GenericAPIView结合mixins形成各种APIView,如CreateAPIView、ListAPIView、ListCreateAPIView、RetrieveUpdateAPIView等;

GenericViewSet继承自ViewSetMixin和GenericAPIView,ViewSetMixin允许且要求在urls.py中通过router进行方法的绑定或者自定义绑定,viewsets还实现了initialize_request(request, *args, **kwargs)方法,绑定了很多action,有很多好处,同时还实现了一些组合,包括ReadOnlyModelViewSet、ModelViewSet等。

相关文章
|
26天前
|
存储 缓存 前端开发
Django 后端架构开发:存储层调优策略解析
Django 后端架构开发:存储层调优策略解析
36 2
|
22天前
|
JavaScript 前端开发 开发者
哇塞!Vue.js 与 Web Components 携手,掀起前端组件复用风暴,震撼你的开发世界!
【8月更文挑战第30天】这段内容介绍了Vue.js和Web Components在前端开发中的优势及二者结合的可能性。Vue.js提供高效简洁的组件化开发,单个组件包含模板、脚本和样式,方便构建复杂用户界面。Web Components作为新兴技术标准,利用自定义元素、Shadow DOM等技术创建封装性强的自定义HTML元素,实现跨框架复用。结合二者,不仅增强了Web Components的逻辑和交互功能,还实现了Vue.js组件在不同框架中的复用,提高了开发效率和可维护性。未来前端开发中,这种结合将大有可为。
65 0
|
26天前
|
存储 安全 数据安全/隐私保护
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
63 0
|
26天前
|
负载均衡 应用服务中间件 网络安全
Django后端架构开发:Nginx服务优化实践
Django后端架构开发:Nginx服务优化实践
36 2
|
26天前
|
消息中间件 存储 监控
Django后端架构开发:Celery异步调优,任务队列和调度
Django后端架构开发:Celery异步调优,任务队列和调度
40 1
|
21天前
|
C++ Python
Django视图函数VS类视图:如何选择最适合你的开发方式?
【8月更文挑战第31天】本文对比了Django中的函数视图和类视图。函数视图直接处理HTTP请求和响应,灵活且易于维护,适用于简单业务逻辑;类视图基于Python类,提供更丰富的功能和更高的灵活性,适合处理复杂业务逻辑。选择哪种视图取决于具体需求,合理使用两者可帮助你构建高效且易维护的Django应用。
12 0
|
22天前
|
JavaScript 开发者 UED
Vue.js 错误处理与调试:跟上技术潮流,摆脱开发困扰,成为代码大神不是梦!
【8月更文挑战第30天】在 Vue.js 开发中,错误处理与调试至关重要。本文将对比 Vue 的全局错误捕获机制 `Vue.config.errorHandler` 和组件内 `watch` 监听数据变化的方式,并介绍 Vue 开发者工具、控制台打印 (`console.log`) 以及代码断点 (`debugger`) 等调试方法。此外,还将探讨如何通过自定义错误页面提升用户体验。通过这些技巧的对比,帮助开发者灵活选择适合的策略,确保应用稳定性和开发效率。
39 0
|
22天前
|
JavaScript 前端开发 API
全栈开发革命来临!Vue.js与Node.js联手,打造前后端无缝对接的奇迹之作!
【8月更文挑战第30天】在Web开发领域,前后端分离与协作至关重要。Vue.js以其轻量级和易用性深受前端开发者喜爱,而Node.js则以高性能和事件驱动特性在后端领域崭露头角。二者结合开启了全栈开发新篇章,通过RESTful API或GraphQL实现高效稳定通信。本文以示例说明如何使用Vue.js和Node.js构建全栈应用,从前端Vue组件到后端Express服务器,展示了数据获取与展示的全过程。这种组合提供了一种高效简洁的全栈开发方案,使开发者能更专注于业务逻辑实现。
45 0
|
22天前
|
JavaScript 前端开发 UED
揭秘Vue.js高效开发:Vue Router如何让单页面应用路由管理变得如此简单?
【8月更文挑战第30天】随着Web应用复杂性的增加,单页面应用(SPA)因出色的用户体验和高效的页面加载性能而备受青睐。Vue.js凭借简洁的语法和灵活的组件系统成为构建SPA的热门选择,其官方路由管理器Vue Router则简化了路由管理。本文通过实战示例介绍如何利用Vue Router实现高效的SPA路由管理,包括命名路由、动态路由及其核心优势。
12 0
|
22天前
|
存储 JavaScript 前端开发
【Vue.js的神秘力量】一键解锁:如何让Bootstrap和Vuex成为你的开发超能力?
【8月更文挑战第30天】Vue.js是一个轻量且灵活的JavaScript框架,易于上手且功能强大。为提高开发效率和应用交互性,常需集成第三方库。本文介绍如何在Vue.js项目中集成Bootstrap和Vuex,及其它常见第三方库。Bootstrap提供响应式设计和预制组件,通过安装插件和引入CSS/JS即可集成;Vuex作为官方状态管理库,通过安装并创建store来管理组件状态。此外,Vue.js还可轻松集成Axios和Vue Router等库,提升HTTP请求和页面路由功能。合理选择和集成第三方库能显著提升开发效率,但需保持代码可维护性和可读性。
16 0