欢迎访问我的博客专题

源码可访问 Github 查看

DRF实现商品分类获取

实现商品分类层级结构显示

商品类别ViewSet

在商品类别中,不需要对类别进行分页,因为类别的数据量不大,只要在数据量很大的时候才能分页,所以前面需要去掉全局分页配置,否则会影响这儿的结果。

修改 views.py 增加分类的视图

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

# 注释很有用,在drf文档中,可以自动提取出来

"""

list:

商品分类列表

"""

queryset = GoodsCategory.objects.all() # 取出所有分类,没必要分页,因为分类数据量不大

serializer_class = CategorySerializer # 使用商品类别序列化类,写商品的分类外键已有,直接调用

该序列化类可以直接使用之前商品列表分类外键已经创建好的,不用再新建,下方是已有的代码内容

class CategorySerializer(serializers.ModelSerializer):

class Meta:

model = GoodsCategory

fields = '__all__'

商品类别URL配置

修改主 urls.py ,在router中注册分类的url

from rest_framework.routers import DefaultRouter

from goods.views import GoodsListView, GoodsListViewSet, CategoryViewSet

# 创建一个路由器并注册我们的视图集

router = DefaultRouter()

router.register(r'goods', GoodsListViewSet, base_name='goods') # 配置goods的url

router.register(r'categories', CategoryViewSet, base_name='categories') # 配置分类的url

urlpatterns = [

path('admin/', admin.site.urls),

path('api-auth/', include('rest_framework.urls')), # drf 认证url

path('ckeditor/', include('ckeditor_uploader.urls')), # 配置富文本编辑器url

path('', include(router.urls)), # API url现在由路由器自动确定。

# DRF文档

path('docs/', include_docs_urls(title='DRF文档')),

]

image.png

但是,这些分类数据都是一起显示出来的,没有层次结构。

层次化商品类别

首先访问 http://127.0.0.1:8000/goods/ 记录下每一种商品的分类外键数据,因为之后要修改分类的序列化类,可以做下对比

image.png

分析:在前端页面上,拿分类数据时,首先是拿到一类分类,二级分类是在一级分类下面的,三级分类是二级分类下面的,可以看出,分类数据是有个层次结构的。

image.png

ViewSet只获取一级分类

既然这样,我们就可以在视图中指定只获取一级分类数据。

修改 views.py

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

# 注释很有用,在drf文档中

"""

list:

商品分类列表

"""

# queryset = GoodsCategory.objects.all() # 取出所有分类,没必要分页,因为分类数据量不大

queryset = GoodsCategory.objects.filter(category_type=1) # 只获取一级分类数据

serializer_class = CategorySerializer # 使用商品类别序列化类,写商品的分类外键已有,直接调用

image.png

那怎么才能通过一级分类获取到二级分类数据呢?之前写商品列表需要显示分类外键内容时,通过覆写category自定义序列化类实现。

序列化二级分类

在分类模型中,有个parent_category = models.ForeignKey('self', null=True, blank=True, verbose_name='父级目录', help_text='父级目录', on_delete=models.CASCADE, related_name='sub_category')字段,也就是可以通过sub_category字段获取子类对象。序列化类的字段也需要和这个字段保持一样。

修改 serializers.py

class CategorySerializer2(serializers.ModelSerializer):

class Meta:

model = GoodsCategory

fields = '__all__'

class CategorySerializer(serializers.ModelSerializer):

sub_category = CategorySerializer2(many=True) # 通过一级分类获取到二级分类,由于一级分类下有多个二级分类,需要设置many=True

class Meta:

model = GoodsCategory

fields = '__all__'

image.png

序列化三级分类

三级分类也是使用一样的办法,因为分类数据的格式都是一样的

修改 serializers.py ,增加三级分类序列化

class CategorySerializer3(serializers.ModelSerializer):

class Meta:

model = GoodsCategory

fields = '__all__'

class CategorySerializer2(serializers.ModelSerializer):

sub_category = CategorySerializer3(many=True) # 通过二级分类获取三级分类

class Meta:

model = GoodsCategory

fields = '__all__'

class CategorySerializer(serializers.ModelSerializer):

sub_category = CategorySerializer2(many=True) # 通过一级分类获取到二级分类,由于一级分类下有多个二级分类,需要设置many=True

class Meta:

model = GoodsCategory

fields = '__all__'

image.png

通过以上修改后,商品列表页也会跟着发生变化,显示的商品分类,会增加子类的显示

image.png

显示某个分类详情(包含其子类)

类似于获取详情页

修改视图,增加mixins.RetrieveModelMixin这样一个mixins

class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):

# 注释很有用,在drf文档中

"""

list:

商品分类列表

"""

# queryset = GoodsCategory.objects.all() # 取出所有分类,没必要分页,因为分类数据量不大

queryset = GoodsCategory.objects.filter(category_type=1) # 只获取一级分类数据

serializer_class = CategorySerializer # 使用商品类别序列化类,写商品的分类外键已有,直接调用

这个继承主要是获取某个对象的详情,且这只需要这样写即可。

Restful Api规范中要获取某个对象的详情,只需要在其后面添加某个对象的ID即可。

DRF已经做好了,不需要手动配置获取详情的URL,只需要在ViewSe中继承mixins.RetrieveModelMixin即可,其他什么都不需要

image.png

image.png

在Vue中获取分类API显示前端

vue中存放分类菜单的位置在 src/views/head/head.vue 中

没有数据,按 F12 打开打开Console可以看到错误内容

Access to XMLHttpRequest at 'http://localhost:8000/categories/' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

也就是不允许跨域请求。因为服务器启动的端口是8000,而Vue启动的是8080端口。就需要配置服务器的跨域(前端也可以配置跨域)。

跨域处理django-cors-headers

解决办法: 查看 https://github.com/ottoyiu/django-cors-headers (Django应用程序处理跨源资源共享(CORS)所需的服务器头),下方有说明使用方法

使用pip安装包,pip install django-cors-headers

将corsheaders应用添加到APPS中

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

# 添加drf应用

'rest_framework',

'django_filters',

# Django跨域解决

'corsheaders',

# 注册富文本编辑器ckeditor

'ckeditor',

# 注册富文本上传图片ckeditor_uploader

'ckeditor_uploader',

'users.apps.UsersConfig',

'goods.apps.GoodsConfig',

'trade.apps.TradeConfig',

'user_operation.apps.UserOperationConfig'

]

还需要添加一个中间件类来监听响应:

MIDDLEWARE = [

'corsheaders.middleware.CorsMiddleware', # corsheaders跨域

'django.middleware.common.CommonMiddleware', # corsheaders跨域

'django.middleware.security.SecurityMiddleware',

'django.contrib.sessions.middleware.SessionMiddleware',

'django.middleware.common.CommonMiddleware',

'django.middleware.csrf.CsrfViewMiddleware',

'django.contrib.auth.middleware.AuthenticationMiddleware',

'django.contrib.messages.middleware.MessageMiddleware',

'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

CorsMiddleware应该放在尽可能前面的位置,尤其是在任何能够生成响应的中间件之前,比如Django的CommonMiddleware或Whitenoise的WhiteNoiseMiddleware。如果不在这之前,它将不能将CORS头添加到这些响应中。

另外,如果正在使用CORS_REPLACE_HTTPS_REFERER,那么它应该放在Django的CsrfViewMiddleware之前。

全局配置:

Django设置中配置中间件的行为。必须将允许执行跨站点请求的主机添加到CORS_ORIGIN_WHITELIST,或者将CORS_ORIGIN_ALLOW_ALL设置为True以允许所有主机。

CORS_ORIGIN_ALLOW_ALL:如果是True,白名单将不被使用,所有的连接将被接受。默认值为False。

CORS_ORIGIN_WHITELIST:授权发出跨站点HTTP请求的源主机名列表。值“null”也可以出现在这个列表中,并将与“隐私敏感上下文”中使用的Origin: null头匹配,例如当客户机从file:// domain运行时。默认为[]。

修改 settings.py ,增加CORS配置

# 跨域CORS设置

# CORS_ORIGIN_ALLOW_ALL = False # 默认为False,如果为True则允许所有连接

CORS_ORIGIN_WHITELIST = ( # 配置允许访问的白名单

'localhost:8080',

'127.0.0.1:8080',

)

image.png

Vue显示分类菜单流程分析

使用axios请求分类数据的api: src/api/api.js

//获取商品类别信息

export const getCategory = params => {

if ('id' in params) {

return axios.get(`${local_host}/categories/` + params.id + '/');

}

else {

return axios.get(`${local_host}/categories/`, params);

}

};

在这个代码中,如果没有获取到id,则请求所有的分类,否则请求指定分类id的详情。

从getCategory拿到数据之后,取results的值(也就是Django Api的是数据部分)赋值给,allMenuLabel,默认为[], head/head.vue

getMenu() {//获取菜单

getCategory({

params: {}

}).then((response) => {

console.log('输出分类列表请求结果:');

console.log(response.data);

this.allMenuLabel = response.data.results

})

.catch(function (error) {

console.log(error);

});

},

image.png

进行allMenuLabel在vue中 for循环的遍历,显示类别的name

全部商品分类

  • {{item.name}}

    {{second_item.name}}

    {{third_item.name}}

遍历三级,显示每一级的分类信息。

分类显示到导航

到目前为止,分类可以正常显示,但是上方的tab没有显示一项,就只有首页,对应源码如下, head/head.vue

  • 首页

  • {{item.name}}

在后台中,所有的分类对象is_tab字段都是为False,默认不显示在导航中。在Django Admin中设置一些一级分类is_tab为True

修改 goods/admin.py ,设置商品类别后台

from django.contrib import admin

from .models import GoodsCategory, Goods

from django.apps import apps

@admin.register(GoodsCategory)

class GoodsCategoryAdmin(admin.ModelAdmin):

list_display = ['name', 'category_type', 'is_tab', 'parent_category'] # 列表页显示

list_display_links = ('name', 'parent_category',) # 列表页外键链接,字段需在list_display中

list_editable = ('is_tab',) # 列表页可编辑

list_filter = ('category_type',) # 列表页可筛选

search_fields = ('name', 'desc') # 列表页可搜索

all_models = apps.get_app_config('goods').get_models()

for model in all_models:

try:

admin.site.register(model)

except:

pass

image.png

image.png

vue一级分类和耳机分类_【Vue+DRF生鲜电商】10.商品分类层级获取,Vue跨域请求商品分类...相关推荐

  1. 【Vue+DRF生鲜电商】27.支付宝公钥,私钥,沙箱环境配置

    专题:Vue+Django REST framework前后端分离生鲜电商 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频). Github地址:http ...

  2. 【Vue+DRF生鲜电商】28.支付宝支付接口类解读,支付逻辑编辑

    专题:Vue+Django REST framework前后端分离生鲜电商 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频). Github地址:http ...

  3. java产品分类和管理_Java生鲜电商平台-商品无限极目录的设计与架构

    Java生鲜电商平台-商品无限极目录的设计与架构 说明:任何一个商品都应该是先属于某一个目录,然后在目录中添加商品,目录理论上最多支持三级,因为级别太多,不容易管理.但是设计中需要设计无限制的级别. ...

  4. node服务器放vue项目,本地Vue项目跨域请求本地Node.js服务器的配置方法

    前言:跨域请求是在本地开发时经常遇到的需求,也很简单,只是几句代码配置一下的问题.我初次配置跨域请求时由于官方的说明太简洁,找到的教程又落伍,调试了一番并没有解决问题,到最后解决问题,已花费了很多时间 ...

  5. vue加跨域代理静态文件404_解决vue本地环境跨域请求正常,版本打包后跨域代理不起作用,请求不到数据的方法——针对vue2.0...

    问题:在本地使用了proxyTable代理可以正常跨域请求后台数据,打包上传后就无法获得后台的json文件.查看了相关资料可以用nginx进行解决.还可以使用命名环境变量,请求的时候进行判断,话不多说 ...

  6. 解决vue axios跨域请求发送两次问题

    解决vue axios跨域请求发送两次问题 参考文章: (1)解决vue axios跨域请求发送两次问题 (2)https://www.cnblogs.com/wordblog/p/12171875. ...

  7. vue 使用axios 出现跨域请求的两种解决方法

    vue 使用axios 出现跨域请求的两种解决方法 参考文章: (1)vue 使用axios 出现跨域请求的两种解决方法 (2)https://www.cnblogs.com/wangshengli5 ...

  8. JAVA毕设项目社区电商平台系统(java+VUE+Mybatis+Maven+Mysql)

    JAVA毕设项目社区电商平台系统(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Web ...

  9. python vue+flask 跨域请求

    刚部署好vue,vue作为前端,flask作为后端,在开发.测试的时候不配置nginx的时候,使用不同端口启动flask.vue,然后使用跨域请求交换数据(也可使用jsonp),在前端和后端分别允许跨 ...

最新文章

  1. python函数绘制5个太阳花_python_bomb----函数
  2. 两个ListBox的相互操作
  3. Qt之QSpacerItem
  4. 44 SD配置-销售凭证设置-定义状态参数文件
  5. python三引号的作用及用法
  6. python2.7 tab,自动补全
  7. php 属性名字访问,php – 如何使用连字符的名称访问此对象属性?
  8. 【Cisco NA】单臂路由+DHCP+DHCP中继+GRE Tunnel
  9. iOS学习笔记(1)— UIView 渲染和内容管理
  10. DIV+CSS的命名规则有利于SEO
  11. ffmpeg 推流MP4文件,采用rtmp协议
  12. [资源分享]yslow 与firebug 修复版本Firefox35【绿色版本下载】
  13. NoSQL数据库Redis--1
  14. 计算机大赛鼓励语录,比赛前的鼓励的话
  15. JAVA学习日志 关于周易数字卦的一个算法
  16. IP地址的划分(A/B/C/D/E)类
  17. 2022年深圳技能大赛-大数据技术应用职业技能竞赛介绍
  18. matlab提取车牌字符程序,matlab - 如何使用Matlab提取和识别车牌号?
  19. 基于 xbot 实现微信关键词自动回复
  20. vue的两种路由模式原理

热门文章

  1. 扇区示意图计算机组成原理,计算机组成原理本.ppt
  2. php+cul+post,php curl封装类使用例子_PHP教程
  3. bash: /etc/apt/sources.list: 权限不够的解决办法
  4. php根据指定时间日历,php学习笔记(十三)时间处理与日历的实现
  5. python教程:循环(while和for)
  6. python嵌套列表知多少
  7. Python里三个最高逼格的调试神器
  8. c#(服务器)与java(客户端)通过socket传递对象_C#(服务器)与Java(客户端)通过Socket传递对象...
  9. Linux 交换内存空间原理(swap)(Linux内存管理)(cgroups)
  10. 黑马程序员C语言基础(第七天)内存管理