• Django+Vue打造购物网站(四)


    首页商品类别数据显示

    商品分类接口

    大概需要两个,一个显示三个类别

    一个显示类别及类别下的全部商品

    现在开始写商品的接口
    首先编写三个分类的serializer

    class CategorySerializer3(serializers.ModelSerializer):
        '''
        三级分类
        '''
    
        class Meta:
            model = GoodsCategory
            fields = "__all__"
    
    
    class CategorySerializer2(serializers.ModelSerializer):
        '''
        二级分类
        '''
        # 在parent_category字段中定义的related_name="sub_cat"
        sub_cat = CategorySerializer3(many=True)
    
        class Meta:
            model = GoodsCategory
            fields = "__all__"
    
    
    class CategorySerializer(serializers.ModelSerializer):
        """
        商品一级类别序列化
        """
        sub_cat = CategorySerializer2(many=True)
    
        class Meta:
            model = GoodsCategory
            fields = "__all__"
    

    然后编写视图函数

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

    配置url

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

    注释的内容会显示在文档中
    mixins.RetrieveModelMixin可以查看单个分类
    前面已经配置过文档的url了

    vue展示商品分类数据

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

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

    替换商品类别默认的host

    //获取商品类别信息
    export const getCategory = params => {
      if('id' in params){
        return axios.get(`${local_host}/categorys/`+params.id+'/');
      }
      else {
        return axios.get(`${local_host}/categorys/`, params);
      }
    };
    

    打开浏览器,可以看到,数据并没有显示出来,
    是因为这涉及到了跨域问题,接下来就解决跨域的问题

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

    https://github.com/ottoyiu/django-cors-headers
    安装模块

    pip install django-cors-headers
    

    添加到INSTALL_APPS中

    INSTALLED_APPS = (
        'corsheaders',
    )
    

    添加中间件
    CorsMiddleware应尽可能放置,特别是在可以生成响应的任何中间件之前,例如Django CommonMiddleware或Whitenoise WhiteNoiseMiddleware。如果不是之前,它将无法将CORS标头添加到这些响应中。

    此外,如果你使用CORS_REPLACE_HTTPS_REFERER它应该放在Django之前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',
    ]
    

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

    这里先允许所有主机跨域,等部署后可以直接将主机ip或域名添加到CORS_ORIGIN_WHITELIST

    # 跨域
    CORS_ORIGIN_ALLOW_ALL = True
    

    打开浏览器进行访问,会发现导航里面没有数据,这是因为后台没有进行设置,需要在后台进行设置

    vue展示商品列表页数据

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

        getListData() {
            if(this.pageType=='search'){
              getGoods({
                search: this.searchWord, //搜索关键词
              }).then((response)=> {
                this.listData = response.data.results;
                this.proNum = response.data.count;
              }).catch(function (error) {
                console.log(error);
              });
            }else {
              getGoods({
                page: this.curPage, //当前页码
                top_category: this.top_category, //商品类型
                ordering: this.ordering, //排序类型
                pricemin: this.pricemin, //价格最低 默认为‘’ 即为不选价格区间
                pricemax: this.pricemax // 价格最高 默认为‘’
              }).then((response)=> {
    
                this.listData = response.data.results;
                this.proNum = response.data.count;
              }).catch(function (error) {
                console.log(error);
              });
            }
    
        },
    

    根据前端内容修改后端分页的参数

    class GoodsPagination(PageNumberPagination):
        '''
        商品列表自定义分页
        '''
        # 默认每页显示的个数
        page_size = 12
        # 可以动态改变每页显示的个数
        page_size_query_param = 'page_size'
        # 页码参数 http://127.0.0.1:8000/goods/?page=2&page_size=30
        page_query_param = 'page'
        # 每页最多能显示多少体条
        # 仅当 page_size_query_param 设置时有效
        max_page_size = 20
    

    通过vue代码可以看到url参数中有一个top_category
    需要给这个参数添加过滤方法

    class GoodsFilter(django_filters.rest_framework.FilterSet):
        '''
        商品过滤的类
        '''
        # 两个参数,field_name是要过滤的字段,lookup是执行的行为,‘小与等于本店价格’
        pricemin = django_filters.NumberFilter(field_name="shop_price", lookup_expr='gte', label='最低价')
        pricemax = django_filters.NumberFilter(field_name="shop_price", lookup_expr='lte', label='最高价')
        top_category = django_filters.NumberFilter(method='top_category_filter', label='分类ID')
    
        # 自定义过滤方法,不管当前点击的是一级分类二级分类还是三级分类,都能找到。
        def top_category_filter(self, queryset, name, value):
            return queryset.filter(Q(category_id=value) | Q(category__parent_category_id=value) | Q(
                category__parent_category__parent_category_id=value))
    
        class Meta:
            model = Goods
            fields = ['pricemin', 'pricemax']
    

    通过浏览器可以进行测试
    在后台查找某一分类下的商品,然后在前台点击进行对比

    修改排序
    前台是按照销量和价格进行排序的,修改后端代码

       #排序
        ordering_fields = ('sold_num', 'shop_price')
    

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

  • 相关阅读:
    通过理解List和IList的区别,加深对接口回调的理解
    mysql学习笔记之mysqlparameter(摘)
    MSSQL表中字段更新后,视图中的字段不更新的解决办法
    如何设置firefox,使其可以支持剪贴板
    CSS图片下载器
    VS2008下.NET 单元测试工具 NUnit2.5 配置与集成方法
    discuz x1.5通过uchome注册后免激活补丁(自动激活)
    (转)七秘诀工作效率与薪水翻番
    TRIGGER OF ORACLE
    SQL LOADER 的使用
  • 原文地址:https://www.cnblogs.com/gaoyongjian/p/9985739.html
Copyright © 2020-2023  润新知