(1)商品分类有两个接口:

一种是全部分类:一级二级三级

 

 

  一种是某一类的分类以及商品详细信息:

 

 开始写商品分类的接口

(2)序列化

给分类添加三级分类的serializer

 goods/serializers.py

  1. from rest_framework import serializers
  2. from .models import Goods,GoodsCategory
  3. class CategorySerializer3(serializers.ModelSerializer):
  4. '''三级分类'''
  5. class Meta:
  6. model = GoodsCategory
  7. fields = "__all__"
  8.  
  9.  
  10. class CategorySerializer2(serializers.ModelSerializer):
  11. '''
  12. 二级分类
  13. '''
  14. #在parent_category字段中定义的related_name="sub_cat"
  15. sub_cat = CategorySerializer3(many=True)
  16. class Meta:
  17. model = GoodsCategory
  18. fields = "__all__"
  19.  
  20.  
  21. class CategorySerializer(serializers.ModelSerializer):
  22. """
  23. 商品一级类别序列化
  24. """
  25. sub_cat = CategorySerializer2(many=True)
  26. class Meta:
  27. model = GoodsCategory
  28. fields = "__all__"

(3)views.py

  1. class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
  2. '''
  3. list:
  4. 商品分类列表数据
  5. '''
  6. queryset = GoodsCategory.objects.filter(category_type=1)
  1. serializer_class = CategorySerializer

说明:

  • 注释的内容,在后面生成drf文档的时候会显示出来,所有要写清楚
  • 要想获取某一个商品的详情的时候,继承 mixins.RetrieveModelMixin  就可以了

 (4)url配置

  1. # 配置Category的url
  2. router.register(r'categorys', CategoryViewSet, base_name="categorys")

 

 接口相关代码都放在src/api/api.js里面,调试接口的时候我们首先需要新建一个自己的host,然后替换要调试的host

(1)新建local_host

  1. let local_host = 'http://127.0.0.1:8000'

(2)替换商品类别默认的host

  1. //获取商品类别信息
  2. export const getCategory = params => {
  3. if('id' in params){
  4. return axios.get(`${local_host}/categorys/`+params.id+'/');
  5. }
  6. else {
  7. return axios.get(`${local_host}/categorys/`, params);
  8. }
  9. };

这个时候访问 http://127.0.0.1:8080/#/app/home/index

发现不显示商品分类了,是因为这涉及到了跨域问题,接下来就解决跨域的问题

 

drf跨域问题

后端服务器解决跨域问题的方法

(1)安装模块

  1. pip install django-cors-headers

django-cors-headers 使用说明:https://github.com/ottoyiu/django-cors-headers

 (2)添加到INSTALL_APPS中

  1. INSTALLED_APPS = (
  2. ...
  3. 'corsheaders',
  4. ...
  5. )

(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之前。我们直接放在第一个位置就好了

  1. MIDDLEWARE = [
  2. 'corsheaders.middleware.CorsMiddleware',
  3. 'django.middleware.security.SecurityMiddleware',
  4. 'django.contrib.sessions.middleware.SessionMiddleware',
  5. 'django.middleware.common.CommonMiddleware',
  6. 'django.middleware.csrf.CsrfViewMiddleware',
  7. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  8. 'django.contrib.messages.middleware.MessageMiddleware',
  9. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  10. ]

(4)设置为True

  1. CORS_ORIGIN_ALLOW_ALL = True

现在再访问 http://127.0.0.1:8080/#/app/home/index   数据就可以填充进来了

 

 在一级分类中设置为True

 

 

 商品列表页会判断我们是serach还是getGoods

  1. getListData() {
  2. if(this.pageType=='search'){
  3. getGoods({
  4. search: this.searchWord, //搜索关键词
  5. }).then((response)=> {
  6. this.listData = response.data.results;
  7. this.proNum = response.data.count;
  8. }).catch(function (error) {
  9. console.log(error);
  10. });
  11. }else {
  12. getGoods({
  13. page: this.curPage, //当前页码
  14. top_category: this.top_category, //商品类型
  15. ordering: this.ordering, //排序类型
  16. pricemin: this.pricemin, //价格最低 默认为‘’ 即为不选价格区间
  17. pricemax: this.pricemax // 价格最高 默认为‘’
  18. }).then((response)=> {
  19. this.listData = response.data.results;
  20. this.proNum = response.data.count;
  21. }).catch(function (error) {
  22. console.log(error);
  23. });
  24. }
  25. },

说明:

(1)page分页

  1. class GoodsPagination(PageNumberPagination):
  2. '''
  3. 商品列表自定义分页
  4. '''
  5. #默认每页显示的个数
  6. page_size = 12
  7. #可以动态改变每页显示的个数
  8. page_size_query_param = 'page_size'
  9. #页码参数
  10. page_query_param = 'page'
  11. #最多能显示多少页
  12. max_page_size = 100

(2)过滤

top_category是商品的一级分类,需要传入参数:一级分类的id

pricemin和pricemax与前端保持一致

获取一级分类下的所有商品

  1. # goods/filters.py
  2.  
  3. import django_filters
  4. from .models import Goods
  5. from django.db.models import Q
  6. class GoodsFilter(django_filters.rest_framework.FilterSet):
  7. '''
  8. 商品过滤的类
  9. '''
  10. #两个参数,name是要过滤的字段,lookup是执行的行为,‘小与等于本店价格’
  11. pricemin = django_filters.NumberFilter(name="shop_price", lookup_expr='gte')
  12. pricemax = django_filters.NumberFilter(name="shop_price", lookup_expr='lte')
  13. top_category = django_filters.NumberFilter(name="category", method='top_category_filter')
  14. def top_category_filter(self, queryset, name, value):
  15. # 不管当前点击的是一级分类二级分类还是三级分类,都能找到。
  16. return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q(
  17. category__parent_category__parent_category_id=value))
  18. class Meta:
  19. model = Goods
  20. fields = ['pricemin', 'pricemax']

(3)排序

  1. GoodsListViewSetording与前端要一致

  1.    #排序
  2. ordering_fields = ('sold_num', 'shop_price')

 (4)替换为local_host

  1. //获取商品列表
  2. export const getGoods = params => { return axios.get(`${local_host}/goods/`, { params: params }) }

(5)搜索

  1.   #搜索
  2. search_fields = ('name', 'goods_brief', 'goods_desc')

 

现在就可以从后台获取商品的数据了,主要功能

  • 分类过滤
  • 价格区间过滤
  • 显示商品数量
  • 分页
  • 搜索

 

 

所有代码:

  1. # MxShop/urls.py
  2. __author__ = 'derek'
  3.  
  4.  
  5. from django.urls import path,include,re_path
  6. import xadmin
  7. from django.views.static import serve
  8. from MxShop.settings import MEDIA_ROOT
  9. # from goods.view_base import GoodsListView
  10.  
  11. from rest_framework.documentation import include_docs_urls
  12. from goods.views import GoodsListViewSet,CategoryViewSet
  13. from rest_framework.routers import DefaultRouter
  14. router = DefaultRouter()
  15. #配置goods的url
  16. router.register(r'goods', GoodsListViewSet,base_name='goods')
  17. # 配置Category的url
  18. router.register(r'categorys', CategoryViewSet, base_name="categorys")
  19. urlpatterns = [
  20. path('xadmin/', xadmin.site.urls),
  21. path('api-auth/',include('rest_framework.urls')),
  22. path('ueditor/',include('DjangoUeditor.urls' )),
  23. #文件
  24. path('media/<path:path>',serve,{'document_root':MEDIA_ROOT}),
  25. #drf文档,title自定义
  26. path('docs',include_docs_urls(title='仙剑奇侠传')),
  27. #商品列表页
  28. re_path('^', include(router.urls)),
  29. ]

MxShop/urls.py

  1. # goods/filters.py
  2.  
  3. import django_filters
  4. from .models import Goods
  5. from django.db.models import Q
  6. class GoodsFilter(django_filters.rest_framework.FilterSet):
  7. '''
  8. 商品过滤的类
  9. '''
  10. #两个参数,name是要过滤的字段,lookup是执行的行为,‘小与等于本店价格’
  11. pricemin = django_filters.NumberFilter(name="shop_price", lookup_expr='gte')
  12. pricemax = django_filters.NumberFilter(name="shop_price", lookup_expr='lte')
  13. top_category = django_filters.NumberFilter(name="category", method='top_category_filter')
  14. def top_category_filter(self, queryset, name, value):
  15. # 不管当前点击的是一级分类二级分类还是三级分类,都能找到。
  16. return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q(
  17. category__parent_category__parent_category_id=value))
  18. class Meta:
  19. model = Goods
  20. fields = ['pricemin', 'pricemax']

goods/filters.py

  1. # goods/serializers.py
  2.  
  3. from rest_framework import serializers
  4. from .models import Goods,GoodsCategory
  5. class CategorySerializer3(serializers.ModelSerializer):
  6. '''三级分类'''
  7. class Meta:
  8. model = GoodsCategory
  9. fields = "__all__"
  10.  
  11.  
  12. class CategorySerializer2(serializers.ModelSerializer):
  13. '''
  14. 二级分类
  15. '''
  16. #在parent_category字段中定义的related_name="sub_cat"
  17. sub_cat = CategorySerializer3(many=True)
  18. class Meta:
  19. model = GoodsCategory
  20. fields = "__all__"
  21.  
  22.  
  23. class CategorySerializer(serializers.ModelSerializer):
  24. """
  25. 商品一级类别序列化
  26. """
  27. sub_cat = CategorySerializer2(many=True)
  28. class Meta:
  29. model = GoodsCategory
  30. fields = "__all__"
  31.  
  32.  
  33. #ModelSerializer实现商品列表页
  34. class GoodsSerializer(serializers.ModelSerializer):
  35. #覆盖外键字段
  36. category = CategorySerializer()
  37. class Meta:
  38. model = Goods
  39. fields = '__all__'

goods/serializers.py

  1. # googd/views.py
  2.  
  3. from rest_framework.views import APIView
  4. from goods.serializers import GoodsSerializer,CategorySerializer
  5. from .models import Goods,GoodsCategory
  6. from rest_framework.response import Response
  7. from rest_framework import mixins
  8. from rest_framework import generics
  9. from rest_framework.pagination import PageNumberPagination
  10. from rest_framework import viewsets
  11. from .filters import GoodsFilter
  12. from django_filters.rest_framework import DjangoFilterBackend
  13. from rest_framework import filters
  14. class GoodsPagination(PageNumberPagination):
  15. '''
  16. 商品列表自定义分页
  17. '''
  18. #默认每页显示的个数
  19. page_size = 12
  20. #可以动态改变每页显示的个数
  21. page_size_query_param = 'page_size'
  22. #页码参数
  23. page_query_param = 'page'
  24. #最多能显示多少页
  25. max_page_size = 100
  26.  
  27.  
  28. class GoodsListViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
  29. '''
  30. 商品列表,分页,搜索,过滤,排序
  31. '''
  32.  
  33. #这里必须要定义一个默认的排序,否则会报错
  34. queryset = Goods.objects.all()
  35. # 分页
  36. pagination_class = GoodsPagination
  37. #序列化
  38. serializer_class = GoodsSerializer
  39. filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter)
  40. # 设置filter的类为我们自定义的类
  41. #过滤
  42. filter_class = GoodsFilter
  43. #搜索
  44. search_fields = ('name', 'goods_brief', 'goods_desc')
  45. #排序
  46. ordering_fields = ('sold_num', 'shop_price')
  47. class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
  48. '''
  49. list:
  50. 商品分类列表数据
  51. '''
  52. queryset = GoodsCategory.objects.filter(category_type=1)
  53. serializer_class = CategorySerializer

goods/views.py

  1. """
  2. Django settings for MxShop project.
  3. Generated by 'django-admin startproject' using Django 2.0.2.
  4. For more information on this file, see
  5. https://docs.djangoproject.com/en/2.0/topics/settings/
  6. For the full list of settings and their values, see
  7. https://docs.djangoproject.com/en/2.0/ref/settings/
  8. """
  9.  
  10. import os, sys
  11. # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
  12. BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  13. sys.path.insert(0, BASE_DIR)
  14. sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
  15. sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
  16. # Quick-start development settings - unsuitable for production
  17. # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/
  18.  
  19. # SECURITY WARNING: keep the secret key used in production secret!
  20. SECRET_KEY = '#r@h(x*x2jc5o^-y#9=9w)o7iiv7jd^zxp@1s5*nj-n*s)v#o*'
  21.  
  22. # SECURITY WARNING: don't run with debug turned on in production!
  23. DEBUG = True
  24. ALLOWED_HOSTS = []
  25. #重载系统的用户,让UserProfile生效
  26. AUTH_USER_MODEL = 'users.UserProfile'
  27.  
  28. # Application definition
  29. INSTALLED_APPS = [
  30. 'django.contrib.admin',
  31. 'django.contrib.auth',
  32. 'django.contrib.contenttypes',
  33. 'django.contrib.sessions',
  34. 'django.contrib.messages',
  35. 'django.contrib.staticfiles',
  36. 'users',
  37. 'goods',
  38. 'trade',
  39. 'user_operation',
  40. 'rest_framework',
  41. 'xadmin',
  42. 'crispy_forms',
  43. 'DjangoUeditor',
  44. 'django_filters',
  45. 'reversion',
  46. 'corsheaders',
  47. ]
  48. MIDDLEWARE = [
  49. 'corsheaders.middleware.CorsMiddleware',
  50. 'django.middleware.security.SecurityMiddleware',
  51. 'django.contrib.sessions.middleware.SessionMiddleware',
  52. 'django.middleware.common.CommonMiddleware',
  53. 'django.middleware.csrf.CsrfViewMiddleware',
  54. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  55. 'django.contrib.messages.middleware.MessageMiddleware',
  56. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  57. ]
  58. CORS_ORIGIN_ALLOW_ALL = True
  59. ROOT_URLCONF = 'MxShop.urls'
  60. TEMPLATES = [
  61. {
  62. 'BACKEND': 'django.template.backends.django.DjangoTemplates',
  63. 'DIRS': [os.path.join(BASE_DIR, 'templates')]
  64. ,
  65. 'APP_DIRS': True,
  66. 'OPTIONS': {
  67. 'context_processors': [
  68. 'django.template.context_processors.debug',
  69. 'django.template.context_processors.request',
  70. 'django.contrib.auth.context_processors.auth',
  71. 'django.contrib.messages.context_processors.messages',
  72. ],
  73. },
  74. },
  75. ]
  76. WSGI_APPLICATION = 'MxShop.wsgi.application'
  77.  
  78.  
  79. # Database
  80. # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
  81. #
  82. # DATABASES = {
  83. # 'default': {
  84. # 'ENGINE': 'django.db.backends.sqlite3',
  85. # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  86. # }
  87. # }
  88. DATABASES = {
  89. 'default': {
  90. 'ENGINE': 'django.db.backends.mysql',
  91. 'NAME': 'mxshop', #数据库名字
  92. 'USER': 'root', #账号
  93. 'PASSWORD': '123456', #密码
  94. 'HOST': '127.0.0.1', #IP
  95. 'PORT': '3306', #端口
  96. #这里引擎用innodb(默认myisam)
  97. #因为后面第三方登录时,要求引擎为INNODB
  98. # 'OPTIONS':{'init_command': 'SET storage_engine=INNODB'}, #按照课程会报错,改为
  99. "OPTIONS":{"init_command":"SET default_storage_engine=INNODB;"}
  100. }
  101. }
  102. # Password validation
  103. # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
  104. AUTH_PASSWORD_VALIDATORS = [
  105. {
  106. 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  107. },
  108. {
  109. 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  110. },
  111. {
  112. 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  113. },
  114. {
  115. 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  116. },
  117. ]
  118. # Internationalization
  119. # https://docs.djangoproject.com/en/2.0/topics/i18n/
  120. LANGUAGE_CODE = 'zh-hans'
  121. TIME_ZONE = 'Asia/Shanghai'
  122. USE_I18N = True
  123. USE_L10N = True
  124. USE_TZ = False
  125. # Static files (CSS, JavaScript, Images)
  126. # https://docs.djangoproject.com/en/2.0/howto/static-files/
  127. STATIC_URL = '/static/'
  128.  
  129. # 设置上传文件的路径
  130. MEDIA_URL="/media/"
  131. MEDIA_ROOT=os.path.join(BASE_DIR,"media")
  132. #
  133. # REST_FRAMEWORK = {
  134. # #分页
  135. # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
  136. # #每页显示的个数
  137. # 'PAGE_SIZE': 10,
  138. # }

settings.py

 

Django REST framework+Vue 打造生鲜超市(四)

Django REST framework+Vue 打造生鲜超市(三)

Django REST framework+Vue 打造生鲜超市(二)

Django REST framework+Vue 打造生鲜超市(一)

 

posted on 2018-04-13 00:30 zhang_derek 阅读() 评论() 编辑 收藏

版权声明:本文为derek1184405959原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/derek1184405959/p/8810591.html