Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善

文章目录

  • Web开发 ------ 基于Django+Vue网上购物商城:项目细节完善
    • 一、支付宝API接口 报错:
    • 二、项目细节完善
      • 1.首页轮播图API接口实现
        • 报错
      • 2.新品API接口实现
      • 3.商品点击数
      • 4.商品收藏数
      • 5.商品库存量
    • 三、Django配置redis缓存
      • 1.安装redis
      • 2.安装django-redis
    • 四、Throttle网站限速
    • 五、后端API开发结束

Web开发 ------ 基于Django+Vue网上购物商城:项目细节完善

完整项目地址:https://gitee.com/dadadaliuliuliiu/ShopProject

一、支付宝API接口 报错:

1.报错:连接不上[2020/4/2 19:36] Upload to shop failed: could not resolve file “sftp://47.105.62.144/”. (Exhausted available authentication methods)
解决:
顶行tools–>development–>configuration–>里面有两个,一个是应用shop,一个是ip47.105.62.144,进行检测Test_Connection,我的是密码不对
2.报错说函数中没有某个方法,点进函数查看,方法是否更新,更改方法名。
3.[Errno 2] No such file or directory: ‘/data/www/ShopProject/app/trade/keys/private_daliu.txt’
原因:可能是写的代码文件没有上传服务器,这里的文件是我从文件夹中直接建立的目录,所以可能不会自动上传。
解决:在pycharm的目录中找到报错文件,右击文件点development–>upload to shop,在运行
4. File “/data/www/ShopProject/app/trade/serializers.py”, line 116, in get_alipay_url
return_url=“http://47.105.62.144:8000/alipay/return/”
ValueError: Not a valid PEM pre boundary
原因:Pycryptodome进行RSA签名,读取文件内的私钥和公钥出错,这里在应用私钥文件、应用公钥文件、支付宝公钥文件里面 内容前后要加上-----BEGIN PUBLIC KEY-----,-----END PUBLIC KEY-----(注意是五个-),我这里出错就是因为写了六个-。
5.问题:在代码没问题运行起来之后,浏览器端访问不了,显示无法访问此网站,可能时阿里云服务器的安全端口没有设置。
解决:登陆阿里云在实例安全组设置8000端口的安全规则,在运行。

二、项目细节完善

1.首页轮播图API接口实现

序列化

class BannerSerializer(serializers.ModelSerializer):
    '''
    轮播图
    '''
    class Meta:
        model = Banner
        fields = "__all__"

视图类

class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    首页轮播图
    """
    queryset = Banner.objects.all().order_by("index")
    serializer_class = BannerSerializer

url配置

# 配置首页轮播图的url 
router.register(r'banners', BannerViewset, basename="banners")

测试
tools里面连接服务器后测试:

[root@todolist-server ~]# cd /data/www/ShopProject/
[root@todolist-server ShopProject]# ls
app                                             manage.py
db.sqlite3                                      media
Django+Vue网上购物商城() 用户交易API接口.pdf  requirements.txt
Django+Vue网上购物商城()   项目细节完善.pdf   ShopProject
Django+Vue网上购物商城()  项目部署.pdf        venv
doc
[root@todolist-server ShopProject]# source venv/bin/activate
(venv) [root@todolist-server ShopProject]# python manage.py runserver 0.0.0.0:8000

此时轮播图为空,去后台添加轮播图来测试
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第1张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第2张图片
在查看banners信息,轮播图添加成功
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第3张图片

报错

1.在首页轮播图API接口完善代码时,TypeError: str returned non-string (type ImageFieldFile)
原因:这里要返回一个图片的名称的字符串 不能是image对象
解决:去goods.models中,修改友好字符串的返回类型:images对象改为返回字符串:return self.image.name
2.如果访问不到可能是本地代码没有上传服务器,访问结果不对可能服务没有更新,需要重启一下服务

2.新品API接口实现

在设计Goods model时候有一个字段is_new, 实现这个接口只要在goods/filters/GoodsFilter里面添加一个过滤就可以了。

class GoodsFilter(django_filters.rest_framework.FilterSet):
    '''
    商品过滤的类
    '''

    class Meta:
        model = Goods
        # http://xxxx/goods/?price_min=10&price_max=100
        fields = ['price_min', 'price_max','is_hot', 'is_new']

测试
在后台设置几个商品 is_new, 前台访问http://IP/goods进行过滤查看新品
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第4张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第5张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第6张图片

3.商品点击数

GoodsListViewSet其中继承了mixins.RetrieveModelMixin(获取商品详情), 当用户浏览该商品详情页信息时,商品点击数+1。
我们只要重写他的retrieve方法就可以了。

Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第7张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第8张图片

# app/goods/views.py 
class GoodsListViewSet(.....):
# 商品点击数 + 1
    def retrieve(self, request, *args, **kwargs):
        """重写retrieve方法, 查看伤情时不仅仅返回商品序列化的信息,还需要修改商品的点击数"""
        instance = self.get_object()
        # ***************** 增加点击数**************************
        instance.click_num += 1
        instance.save()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

测试
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第9张图片

4.商品收藏数

前面已经写了UserFavViewset,其中继承mixins.CreateModelMixin,添加收藏实际就是创建数据库。这里重写它的perform_create方法就可以了。
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第10张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第11张图片

class UserFavViewset(viewsets.GenericViewSet, mixins.ListModelMixin,
                     mixins.CreateModelMixin, mixins.DestroyModelMixin):
    '''
    用户收藏
    '''

	def perform_create(self, serializer):
        # 对象: UserFav商品收藏的对象
        instance = serializer.save()
        # 获取用户收藏的商品对象
        goods = instance.goods
        # 更新收藏商品的收藏数
        goods.fav_num += 1
        # 商品信息修改后保存到数据库中
        goods.save()

测试
收藏id=1的商品,然后去goods/1查看此商品的收藏数,收藏数加1
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第12张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第13张图片
收藏数加1
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第14张图片

5.商品库存量

库存数变化:
1.在购物车中没有这个商品时,增加购物车商品后,goods/ 商品库存减少,
2.在购物车中已经添加了商品时,进入详情页shopcarts/1 更新购物车中的商品,库存也更新。

# app/trade/views.py 
'''
	# 销售量变化:
    #       1. 增加订单并支付成功:
   
    # 库存数变化:
    #       1. 购物车添加商品信息: 库存量-购物车数量
    #       2. 购物车更新商品数量:  - 10 +
    #       3. 删除购物车的商品:   库存量增加
'''

class ShoppingCartViewset(viewsets.ModelViewSet): 
	# .......... 
	# 库存数-1
	def perform_create(self, serializer):
        """重写perform_create方法,商品加入购物车, 存储购物车的商品信息,还要更新商品的库存信息 """
        # serializer.save存储的是购物车的数据库模型对象
        shopcarts = serializer.save()
        # 获取当前购物车的商品对象.
        goods = shopcarts.goods
        goods.goods_num -= shopcarts.nums
        goods.save()

    def perform_destroy(self, instance):
        # serializer.save存储的是购物车的数据库模型对象  商品名称  - 10 +
        shopcarts = instance
        # 获取当前购物车的商品对象.
        goods = shopcarts.goods
        # 购物车里面商品删除, 增加商品的库存量
        goods.goods_num += shopcarts.nums
        # 一定要将更改的信息存储到数据库中.
        goods.save()
        # 将购物车对象删除.
        instance.delete()

    def perform_update(self, serializer):
        """
        当购物车商品数量更新时, 更新商品的库存量(可能增加也可能减少)
            1. 先获取购物车之前商品的数量.    10
            2. 获取购物车现在商品的数量.      9
            3. 发现购物车数量减少1  update_nums = 现在的购物车数量-原先的购物车数量   -1
            4. 100 更新商品库存量加1     100 - (-1) = 101
        """
        # get方法返回的是符合条件的对象, filter返回的是符合条件的列表信息。
        old_shopcart_nums = ShoppingCart.objects.get(id=serializer.instance.id).nums  # 10
        shopcart = serializer.save()
        new_shopcart_nums = shopcart.nums  # 9
        update_nums = new_shopcart_nums - old_shopcart_nums  # -1
        goods = shopcart.goods  # 库存量100
        goods.goods_num -= update_nums  # 库存量100-(-1) = 101
        goods.save()

测试:
库存为0,更新id=1的商品库存为100来测试
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第15张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第16张图片

  • 购物车中没有添加商品时 ,增加删除测试

当原库存为100,加入购物车20个,查看商品库存变为80

Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第17张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第18张图片

进入id=1详情页,删除购物车id=1的商品,查看good商品看库存,增加了20,变为100
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第19张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第20张图片

  • 购物车中原来有商品,想要更改加购的商品数量时测试
    原商品库存100
    购物车shopcarts/添加10个商品,查看goods/商品库存为90,
    进入shopcart/1 详情页 ,更改加购数量为20
    在查看商品库存,变为80
    (这里注意,测试要进入购物车详情页进行更改购物车数量)
    Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第21张图片

三、Django配置redis缓存

1.安装redis

Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第22张图片

1.在服务器上安装redis
这里用阿里的镜像源可以直接yum安装

(venv) [root@todolist-server ShopProject]# yum install redis -y

2.修改redis配置文件
默认绑定的是本机的回环地址127.0.0.1,我们修改为bind 0.0.0.0
这里要注意,配置文件中可能原先有绑定,要先屏蔽掉,一般是后面的会掩盖前面的

(venv) [root@todolist-server ShopProject]#rpm -qc redis  #查询redis配置文件位置
/etc/redis.conf
(venv) [root@todolist-server ShopProject]# vim /etc/redis.conf

3.启动redis服务

(venv) [root@todolist-server ShopProject]# systemctl start redis
(venv) [root@todolist-server ShopProject]# systemctl enable redis
Created symlink from /etc/systemd/system/multi-user.target.wants/redis.service to /usr/lib/systemd/system/redis.service.
(venv) [root@todolist-server ShopProject]# systemctl status redis
● redis.service - Redis persistent key-value database
   Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/redis.service.d
           └─limit.conf
   Active: active (running) since Sun 2020-04-05 15:32:28 CST; 24s ago
 Main PID: 1729 (redis-server)
   CGroup: /system.slice/redis.service
           └─1729 /usr/bin/redis-server 0.0.0.0:6379

Apr 05 15:32:28 todolist-server systemd[1]: Starting Redis persistent key-value database...
Apr 05 15:32:28 todolist-server systemd[1]: Started Redis persistent key-value database.

4.查看redis的端口号和绑定的ip

(venv) [root@todolist-server ShopProject]# netstat -antlpe | grep redis
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      996        866105     1729/redis-server 0 

5.客户端指令测试redis服务器是否连通

(venv) [root@todolist-server ShopProject]# redis-cli -h 47.105.62.144
47.105.62.144:6379> ping
PONG
47.105.62.144:6379> 

2.安装django-redis

为了加速网站的访问速度,将一些数据放到缓存当中,取数据的时候首先去缓存中去,然后再去数据库中取。我们用Redis来实现缓存。
使用django-redis第三方库:http://django-redis-chs.readthedocs.io/zh_CN/latest/#id8 (文档说明)

(venv) [root@todolist-server ShopProject]# pip install django-redis

为了使用django-redis,修改django cache setting

# 跨域
CORS_ORIGIN_ALLOW_ALL = True
# Redis缓存的配置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://47.105.62.144:6379/1",  # 1,代表数据库名为1
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第23张图片
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第24张图片

(venv) [root@todolist-server ShopProject]# redis-cli -h 47.105.62.144
47.105.62.144:6379> select 1
OK
47.105.62.144:6379[1]> keys *
(empty list or set)
47.105.62.144:6379[1]> keys *
1) ":1:throttle_user_1"
2) ":1:xadmin_themes"

四、Throttle网站限速

Throttle可以对接口访问的频次进行限制,以减轻服务器的压力。一般用于付费购买次数,投票等场景使用, 防止网络爬虫多频率访问。
官网使用说明:http://www.django-rest-framework.org/api-guide/throttling/

配置文件

REST_FRAMEWORK = {
    # 。。。。。。
    # 限速设置
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',  # 未登陆用户
        'rest_framework.throttling.UserRateThrottle'  # 登陆用户
    ),
    'DEFAULT_THROTTLE_RATES': {
        # *****************测试配置***********************
        # 'anon': '3/minute',  # 每分钟可以请求3次
        # 'user': '5/minute'  # 每分钟可以请求五次
        # ******************生产环境的配置****************
        'anon': '100/day',
        'user': '1000/day'
    }
}

视图类

class GoodsListViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    """
    list:
    返回商品列表数据
​
    retrieve:
    返回商品详情数据
​
    """

    # 网站限速
    throttle_classes = (UserRateThrottle, AnonRateThrottle)

    # Cache requested url for each user for 2 hours
    @method_decorator(cache_page(60 * 60 * 2))
    @method_decorator(vary_on_cookie)
    def retrieve(self, request, *args, **kwargs):
        """重写retrieve方法, 查看伤情时不仅仅返回商品序列化的信息,还需要修改商品的点击数"""
       #。。。

@method_decorator(cache_page(5), name='dispatch')
class CategoryViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    #。。。

API测试
请求超出限制次数则会出现限制:
Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第25张图片

五、后端API开发结束

将后端API文档47.105.62.144/docs传给前端开发人员

Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善_第26张图片

你可能感兴趣的:(Web开发 ------ 基于Django+Vue网上购物商城(四): 项目细节完善)