django项目中购物车的实现

对于做项目而言,最重要的是分析清楚自己负责模块的思路,确定思路后,把每一步实现的步骤确定后,根据步骤,去实现代码,测试。

购物车的逻辑:
    登录用户可以添加购物车,未登陆用户页可以添加到购物车
    登陆用户的保存user.id sku_id count selected      保存在redis中,以hash和set两种方式保存
    未登陆用户保存sku_id count selectd  保存再cookie中
    cart = {
            sku_id:{count:5,selected:True},
            sku_id:{count:1,selected:True},
            }

后端接口设计:

请求方式:POST /cart/

1、项目中的settings.py中设置

# Application definition
CORS_ALLOW_CREDENTIALS = True   #允许携带cookie访问

2、项目中的settings.py添加数据库redis

CACHES = {
 "cart": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/4",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
}

3、创建子应用cart

在终端的虚拟环境下进入到工程中,执行以下命令

>>>(py3_django_38) [email protected]:~/Desktop/shopping_mall/mall/apps$ python ../manage.py startapp cart

4、在工程的settings.py中添加apps

INSTALLED_APPS = [‘cart.apps.CartConfig‘]   #本质是让工程加载子应用的配置,实质就是子应用配置的路径,可以根据路径查询到子应用的配置

5、在cart/views.py中添加视图

import pickleimport base64

from django_redis import get_redis_connectionfrom rest_framework import statusfrom rest_framework.response import Responsefrom rest_framework.views import APIView

from cart.serializers import CartSerializer

class CartAPIView(APIView):

    ‘‘‘
    因为我们APIView在我们调用http方法前会进行认证
    我们的token过期或者伪造的化,会直接返回401
    这个不符合业务逻辑
    我们的业务逻辑应该是token过期或伪造的化应该认为是一个匿名用户
    匿名用户的购物车数据可以放在cookie中
    对于我们编程而言,应该能够先进入http方法,等验证用户信息是,再验证
    ‘‘‘

    def perform_authentication(self, request):
        pass

    ‘‘‘
    当用户点击添加购物车按钮的时候
    登陆用户需要将token sku_id count 选中状态提交给后端
    未登陆用户需要将  sku_id  count 选中状态提交给后端

    后端:1、接收数据(sku_id count selected)
        2、验证数据 (验证商品的id是否有对应的商品,商品的个数)
        3、获取数据
        4、得到用户信息
        5、根据用户的信息进行判断
        6、登陆用户保存再redis中
            6.1、链接redis
            6.2、保存hash set
            6.3返回响应
        7、未登录用户 保存再cookie中
            7.1 先读取cookie信息
            7.2 判断是否有购物车信息
                如果有 加密处理
                如果没有
            7.3 判断这个商品是否再cookie中
                如果在,累加数据
                如果不在则直接添加
            7.4将购物车数据进行加密处理
            7.5返回响应

    ‘‘‘

    #添加购物车
    def post(self,request):

        # #因为我们是在需要判断的时候再去判断用户的信息 ,所以需要对用户的信息进行异常捕获
        # try:
        #     user = request.user
        #
        # except Exception as e:
        #     user = None
        # pass
        #1、后端接收数据
        data = request.data

        #2、验证数据(对应id是否有商品,商品的个数)
        serializer = CartSerializer(data=data)

        serializer.is_valid(raise_exception=True)

        #获取数据
        sku_id = serializer.validated_data.get(‘sku_id‘)
        count = serializer.validated_data.get(‘count‘)
        selected = serializer.validated_data.get(‘selected‘)

        #4、得到用户的信息
        try:
            user = request.user
        except Exception as e:
            user = None

        #5、根据用户的信息进行判断
            # request.user.is_authenticated
        if user is not None and user.is_authenticated:
            #user不为空,而且是认证用户
            #6、登陆用户保存在redis中
            #6.1链接redis
            redis_conn = get_redis_connection(‘cart‘)
            #6.2保存数据
            #hash
            #具体的存储方式需要查看文档才能确定
            # redis_conn.hset(‘cart_%s‘%user.id,sku_id,count)
            # hash没有进行累加操作 应该累加
            # hincrby 累加操作  累加数据可以是正数页可以是负数
            # redis_conn.hincrby(‘cart_%s‘%user.id,sku_id,count)
            ‘‘‘
            管道
            管道是基础redis类的子类,他为在单个请求中向服务器缓冲多个命令提供技术支持
            他们可以用于通过减少客户端和服务器之间来回的tcp数据包数量来显著提高命令组的性能
            A、创建管道
            pl = redis_conn.pipeline()
            B、将redis指令添加到管道中
            pl.hincrby(‘cart_%s‘%user.id,sku_id,count)

            C、执行管道
            pl.execute()

            ‘‘‘
            pl = redis_conn.pipeline()

            pl.hincrby(‘cart_%s‘%user.id,sku_id,count)

            #set
            if selected:
                # redis_conn.sadd(‘cart_selected_%s‘%user.id,sku_id)
                pl.sadd(‘cart_selected_%s‘%user.id,sku_id)

            pl.execute()
            #6.3返回数据
            return Response(serializer.data)

        else:
            #7、未登录用户保存在cookie中
            #7.1 先读取cookie信息
            cookie_str = request.COOKIES.get(‘cart‘)
            #7.2判断是否有购物车信息
            if cookie_str is not None:
                #如果有,则是加密数据
                #7.2.1  将加密后的数据进行解码
                decode = base64.b64decode(cookie_str)

                #7.2.2 将二进制转化为字典
                cookie_cart = pickle.loads(decode)

            else:
                #如果没有,则定义一个空字典
                cookie_cart = {}

            #7.3判断这个商品是否在cookie中
            if sku_id in cookie_cart:

                #如果在 则累加,
                #先获取之前的数据
                original_count = cookie_cart[sku_id][‘count‘]

                count += original_count

            #如果不在,则直接添加
            cookie_cart[sku_id] = {
                ‘count‘:count,
                ‘selected‘:selected
            }

            #将购物车进行加密处理
            #7.4.1 将字典转化为bytes类型
            dumps = pickle.dumps(cookie_cart)
            #7.4.2 对bytes类型进行编码
            encode = base64.b64encode(dumps)

            #7.5返回响应
            response = Response(serializer.data)

            #为啥要解码呢   将二进制转化为字符串
            response.set_cookie(‘cart‘,encode.decode())

            return response

6、添加序列化器

  cart/serializers.py

from rest_framework import serializers

class CartSerializer(serializers.Serializer):

    sku_id = serializers.IntegerField(label=‘sku_id‘, required=True, min_value=1)
    count = serializers.IntegerField(label=‘数量‘, required=True, min_value=1)
    selected = serializers.BooleanField(label=‘是否勾选‘, required=False, default=True)

    def validate(self, attrs):
        #判断商品是否存在
        sku_id = attrs[‘sku_id‘]
        try:
            sku = SKU.objects.get(pk=sku_id)
        except SKU.DoesNotExist:
            raise serializers.ValidationError(‘商品不存在‘)

        #判断库存是否充足
        count = attrs[‘count‘]
        if sku.stock < count:
            raise serializers.ValidationError(‘库存不足‘)

        return attrs

7、添加路由

7.1在工程的urls.py中添加

urlpatterns = [
    url(r‘^cart/‘,include(‘cart.urls‘)),
]

7.2在cart/urls.py中添加

from django.conf.urls import url

from . import views

urlpatterns = [

    url(r‘^$‘,views.CartAPIView.as_view()),
]

8、添加html和js代码

添加购物车的功能已实现,查询后期再更新

原文地址:https://www.cnblogs.com/goulingyun/p/10714200.html

时间: 2024-12-11 13:46:33

django项目中购物车的实现的相关文章

Django项目中使用Redis

Django项目中使用Redis DjangoRedis 1 redis Redis 是一个 key-value 存储系统,常用于缓存的存储.django-redis 基于 BSD 许可, 是一个使 Django 支持 Redis cache/session 后端的全功能组件. 1.1 为何要用 django-redis ? 持续更新 本地化的 redis-py URL 符号连接字符串 可扩展客户端 可扩展解析器 可扩展序列器 默认客户端主/从支持 完善的测试 已在一些项目的生产环境中作为 ca

django项目中遇到要实现定时任务

django项目中遇到要实现定时任务,所以选用了简单易用的django-crontab插件. 1.安装 django-crontab pip install django-crontab 2.定时要执行的脚本 先写个简单的测试脚本. ipoms/crons.py import datetime def update_stock_status(): start_time = datetime.datetime.now() print start_time, ", begin update_stoc

异步任务利器Celery(二)在django项目中使用Celery

Celery 4.0支持django1.8及以上的版本,低于1.8的项目使用Celery 3.1. 一个django项目的组织如下: - proj/ - manage.py - proj/ - __init__.py - settings.py - urls.py 首先建立proj/proj/celery.py文件: from __future__ import absolute_import, unicode_literals import os from celery import Cele

在Django项目中使用富文本编辑器

1 开发要点 现在网上有很多的富文本编辑器,包括Markdown.tinymce.UEditor.KindEditor.ckeditor等等.在项目中使用这些编辑器主要有以下几个问题: 编辑页面 在HTML页面渲染编辑器: 定制编辑器的功能,比如有哪些文本样式.图片上传.代码插入: 定制编辑器的样式,指的是编辑器整体的样式,比如高度.宽度.显示位置等等: 预览内容: 获取内容: 显示页面 显示内容: 2 Django APP 下表列出一些常用的APP,它们都可以在GitHub上找的到,链接见下文

django项目中使用FastDFS

FastDFS客户端与自定义文件存储系统 1. FastDFS的Python客户端 python版本的FastDFS客户端使用说明参考https://github.com/jefforeilly/fdfs_client-py 安装 安装提供给大家的fdfs_client-py-master.zip到虚拟环境中 pip install fdfs_client-py-master.zippip install mutagenpip isntall requests 使用 使用FastDFS客户端,需

Django项目中的实现rbac功能

一.什么是rbacrbac翻译意思就是(Role-Based Access Contro)基于角色的权限控制 二.优势1.将用户和权限的关系2.易扩展,易于维护 比如张三李四需要用客户列表访问权限,如果上百个用户,单独分配权限会麻烦,如果单独放客户列表权限在销售角色里面,张三李四放到销售角色里就OK了 三.RBAC流程图 第一张:用户表第二张:角色表第三张表:用户表和角色表多对多的关系,一个用户可以有多个角色第四张表:权限表第五张表:权限表和角色表多对多的关系,多个权限可以放到一个角色里面 四.

从数据库反向生成django项目中的models文件

1.创建一个django项目 2.在项目配置文件settings.py中配置好数据库的相关配置 3.确保所关联的数据库中已经有表存在 4.在pycharm终端进入到项目的根目录,执行python manage.py inspectdb,查看可以导入到models的相关信息 5.执行python manage.py inspectdb > (需要导入表的app)/models.py,即可完成反向生成models文件 6.进入models文件进行相关修改 原文地址:https://www.cnblo

django 项目中mysql 的编码,数据库迁移问题

以管理员的身份进入cmd net start mysql mysql -u root -p 没有密码直接回车,进入mysql可以创建数据库, 如退出mysql  执行 \q:命令 创建数据库  记得指定编码    create database orm_1128 character set utf8;  orm_1128是数据库名字 修改数据库的字符集mysql>use mydb mysql>alter database mydb character set utf8; 如果报错, ERROR

Django项目中引用js,css文件的可行方法

首先,在manager.py同层级下创建static文件夹, 里面放上css , js, image等文件或者文件夹 第二,在项目同名的app中settings文件末尾添加以下内容: STATIC_URL = '/static/' HERE = os.path.dirname(os.path.abspath(__file__)) HERE = os.path.join(HERE, '../') STATICFILES_DIRS = ( # Put strings here, like "/hom