一种是全部分类:一级二级三级
一种是某一类的分类以及商品详细信息:
开始写商品分类的接口
因为有三类的种类, 我们先提取第一类的种类.
view.py代码
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters
from .models import Goods, GoodsCategory
from rest_framework import viewsets
from .serializers import GoodsSerializer, CategorySerializer
from .filter import GoodsFilter
from rest_framework.pagination import PageNumberPagination
from rest_framework import generics
class StandardResultsSetPagination(PageNumberPagination):
'''
商品列表自定义分页
'''
# 默认每页显示的个数
page_size = 10
# 可以动态改变每页显示的个数
page_size_query_param = 'page_size'
# 页码参数
page_query_param = 'p'
# 最多能显示多少页
max_page_size = 100
class GoodsListViewSet(viewsets.ModelViewSet):
"""
商品列表页
"""
queryset = Goods.objects.all().order_by('-add_time') # 取出所有对象
serializer_class = GoodsSerializer # 序列化相应的对象
pagination_class = StandardResultsSetPagination # 设置分页参数
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)# 后台过滤设置
filter_class = GoodsFilter # 要过滤的类和字段设置
search_fields = ('=name', 'goods_brief') # 搜索的字段
ordering_fields = ('sold_num', 'add_time') # 排序功能
class CategoryViewSet(viewsets.ModelViewSet):
"""
list:
商品分类列表数据
"""
queryset = GoodsCategory.objects.filter(category_type=1) # 取出所有对象
serializer_class = CategorySerializer # 序列化相应的对象
"""
list:
商品分类列表数据
"""
这一块这么写的原因是后面以便于生产api文档.
urls.py
"""VueShopProject URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.views.static import serve
import xadmin
from VueShopProject.settings import MEDIA_ROOT
from rest_framework import routers
from goods import views
router = routers.DefaultRouter() # 注册默认的路由类
router.register(r'goods', views.GoodsListViewSet) # 添加goods路由信息到路由类
router.register(r'categorys', views.CategoryViewSet)# 添加category路由信息
urlpatterns = [
url('xadmin/', xadmin.site.urls), # xadmin后台url
url(r'^ueditor/', include('DjangoUeditor.urls')), # 富文本编辑器url
url(r'media/(?P.*)$', serve, {'document_root': MEDIA_ROOT}),# mediaurl
url(r'^api-auth/', include('rest_framework.urls')), # drf 路由
url(r'^', include(router.urls)), # drf的路由表
]
运行代码后, 我们看看返回结果.
和我们预期一样, 成功提取, 我们再想想怎么提取第二类类别
怎么来提取第二类呢? 我们先想想第二类和第一类有什么联系吧, 第二类和第一类的联系取决于第二类中定义了一个parent_category字段, 该字段指向上一级, 而该字段有一个属性叫 related_name="sub_cat"
related_name的作用是用于处理外键之间的联系的, 详情见:https://blog.csdn.net/wuliangtianzu/article/details/82656647
在这我们可以通过sub_cat字段来看看有哪些二级类是一级类的, 我们把序列化类做一下修改:serializers.py
from .models import Goods, GoodsCategory
from rest_framework import serializers
class CategorySerializer2(serializers.ModelSerializer):
class Meta:
model = GoodsCategory
fields = "__all__"
class CategorySerializer(serializers.ModelSerializer):
"""
商品类别序列化
"""
sub_cat = CategorySerializer2(many=True)
class Meta:
model = GoodsCategory # 序列化的module
fields = "__all__" # 序列化的字段
class GoodsSerializer(serializers.ModelSerializer):
"""
商品序列化
"""
category = CategorySerializer() # 实例化对象的名字一定要和外键字段的名字一样
class Meta:
model = Goods # 要序列化的类
fields = "__all__" # 要序列化的字段
我们在原来的基础上增加了 CategorySerializer2 类, 和对 CategorySerializer 做了修改
注意: sub_cat = CategorySerializer2(many=True)这一句一定要加many=true, 不然会报如下的错,
我们运行一下功能, 看能不能运行, 访问: http://127.0.0.1:8000/categorys/
得到如下的数据:
返回成功
既然第二类都可以提取了, 而且思路一样, 第三类我就直接贴代码了, serializers.py
from .models import Goods, GoodsCategory
from rest_framework import serializers
class CategorySerializer3(serializers.ModelSerializer):
"""
商品类别3序列化
"""
class Meta:
model = GoodsCategory
fields = "__all__"
class CategorySerializer2(serializers.ModelSerializer):
"""
商品类别2序列化
"""
sub_cat = CategorySerializer3(many=True) # 取类别2下类别3的对象
class Meta:
model = GoodsCategory()
fields = "__all__"
class CategorySerializer(serializers.ModelSerializer):
"""
商品类别1序列化
"""
sub_cat = CategorySerializer2(many=True) # 取类别1下类别2的对象
class Meta:
model = GoodsCategory # 序列化的module
fields = "__all__" # 序列化的字段
class GoodsSerializer(serializers.ModelSerializer):
"""
商品序列化
"""
category = CategorySerializer() # 实例化对象的名字一定要和外键字段的名字一样
class Meta:
model = Goods # 要序列化的类
fields = "__all__" # 要序列化的字段
我们都把全部数据都提取出来了, 但是我们不是要全部类别的数据, 而是只是要一类的数据, 那应该怎么提取, 这个问题呢? drf已经帮我们考虑好了, 在url后面加上相应的id就可以访问对应的类了, 比如, 我想访问id=1的第一类类别, 只需访问:http://127.0.0.1:8000/categorys/1/ 就可以了
如下图所示:
我们来看看怎么展示数据吧, 关于vue的知识我不做解释, 因为vue涉及一大块内容, 解释起来很要时间, 而且我主要是做后端开发, 前端不想深入了解, 来看看怎么展示数据吧.
首先我们得打开vue的源码目录, 如图:
如图打开online-store->src->api->api.js api.js这里存放这整个项目的api设置, 首先我们的改一下如上图所示的host地址, 改为本地的地址和本地的端口, 视频中老师说另起一个变量, 这样做最好了, 因为老师原来的后台已经不能用了, 所以我就索性改为自己的本地地址.
然后运行vue工程, 在onlin-store目录下运行npm run dev 命令, 看看效果:
没有一点效果, 怎么回事, 这是因为涉及到跨域问题, 因为我们后台端口是8000, 而前端是8080 已经跨域了, 解决跨域问题, 前端后台后可以做, 我现在讲讲后台怎么解决跨域问题.
后端服务器解决跨域问题的方法:
(1)安装模块
pip install django-cors-headers
django-cors-headers 使用说明:https://github.com/ottoyiu/django-cors-headers
(2)添加到INSTALL_APPS中
INSTALLED_APPS = ( ...
'corsheaders',
... )
(3)添加中间件
下面添加中间件的说明:
CorsMiddleware
should be placed as high as possible, especially before any middleware that can generate responses such as Django's CommonMiddleware
or Whitenoise's WhiteNoiseMiddleware
. If it is not before, it will not be able to add the CORS headers to these responses.
Also if you are using CORS_REPLACE_HTTPS_REFERER
it should be placed before Django's CsrfViewMiddleware
(see more below).
意思就是 要放的尽可能靠前,必须在CsrfViewMiddleware之前。我们直接放在第一个位置就好了
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'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',
]
(4)设置为True(在setting下)
CORS_ORIGIN_ALLOW_ALL = True
现在再访问 http://127.0.0.1:8080/#/app/home/index 数据就可以填充进来了
在一级分类中设置为True