路飞项目深科技相关表结构及购物车

# ######################## 深科技相关 ########################
class ArticleSource(models.Model):
    """文章来源"""
    name = models.CharField(max_length=64, unique=True)

    class Meta:
        verbose_name_plural = "16. 文章来源"

    def __str__(self):
        return self.name

class Article(models.Model):
    """文章资讯"""
    title = models.CharField(max_length=255, unique=True, db_index=True, verbose_name="标题")
    source = models.ForeignKey("ArticleSource", verbose_name="来源")
    article_type_choices = ((0, '资讯'), (1, '视频'))
    article_type = models.SmallIntegerField(choices=article_type_choices, default=0)
    brief = models.TextField(max_length=512, verbose_name="摘要")
    head_img = models.CharField(max_length=255)
    content = models.TextField(verbose_name="文章正文")
    pub_date = models.DateTimeField(verbose_name="上架日期")
    offline_date = models.DateTimeField(verbose_name="下架日期")
    status_choices = ((0, '在线'), (1, '下线'))
    status = models.SmallIntegerField(choices=status_choices, default=0, verbose_name="状态")
    order = models.SmallIntegerField(default=0, verbose_name="权重", help_text="文章想置顶,可以把数字调大,不要超过1000")
    vid = models.CharField(max_length=128, verbose_name="视频VID", help_text="文章类型是视频, 则需要添加视频VID", blank=True, null=True)
    comment_num = models.SmallIntegerField(default=0, verbose_name="评论数")
    agree_num = models.SmallIntegerField(default=0, verbose_name="点赞数")
    view_num = models.SmallIntegerField(default=0, verbose_name="观看数")
    collect_num = models.SmallIntegerField(default=0, verbose_name="收藏数")

    # tags = models.ManyToManyField("Tags", blank=True, verbose_name="标签")
    date = models.DateTimeField(auto_now_add=True, verbose_name="创建日期")

    position_choices = ((0, '信息流'), (1, 'banner大图'), (2, 'banner小图'))
    position = models.SmallIntegerField(choices=position_choices, default=0, verbose_name="位置")


    #comment = GenericRelation("Comment")

    class Meta:
        verbose_name_plural = "17. 文章"

    def __str__(self):
        return "%s-%s" % (self.source, self.title)

class Collection(models.Model):
    """收藏"""
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    account = models.ForeignKey("Account")
    date = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ('content_type', 'object_id', 'account')
        verbose_name_plural = "18. 通用收藏表"

class Comment(models.Model):
    """通用的评论表"""
    content_type = models.ForeignKey(ContentType, blank=True, null=True, verbose_name="类型")
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content_object = GenericForeignKey('content_type', 'object_id')

    p_node = models.ForeignKey("self", blank=True, null=True, verbose_name="父级评论")
    content = models.TextField(max_length=1024)
    account = models.ForeignKey("Account", verbose_name="会员名")
    disagree_number = models.IntegerField(default=0, verbose_name="踩")
    agree_number = models.IntegerField(default=0, verbose_name="赞同数")
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.content

    class Meta:
        verbose_name_plural = "19. 通用评论表"

class Account(models.Model):
    username = models.CharField("用户名", max_length=64, unique=True)
    password = models.CharField("密码", max_length=64)

class UserAuthToken(models.Model):
    """
    用户Token表
    """
    user = models.OneToOneField(to="Account")
    token = models.CharField(max_length=64, unique=True)

 路飞的深科技结构?

  • -文章来源
  • -文章详细
  • -收藏
  • -点赞
  • -评论
  • -用户
  • -用户token

路飞购物车

加入购物车,保存到redis。

  •  因为购物车只是一个暂时的状态,当结算完成的实收会删除购物车的内容.且购物车的操作可能比较频繁,因为客户会考虑的比较多
  • 如果只用数据库的话,那么每次修改都对数据库进行修改,数据库的压力会比较大.
  • 如果用redis+数据库,比如一天放到redis里,然后12点后存放到数据库.这个方案也是可以
    •  但是如果存在数据库,那么就需要一个购物车的表结构.
    •  而reids可以不用创建表结构,就能完成同样的事情,而且性能更高
     

路飞购物车字典是如何构造的?

    {    # luffy_shopping_car_用户id_课程id
        luffy_shopping_car_6_1:{
                        'title':'xxxxx',
                        'img':'xxx'
                        'prolicy':{
                            10:{'name':'有效期1个月','price':123},
                            11:{'name':'有效期1个月','price':123},
                            12:{'name':'有效期1个月','price':123},
                        'defalut_prolicy':10,
                        },
        },
        luffy_shopping_car_6_2:{
        ...
        },
        luffy_shopping_car_6_3:{
        ...
        }
    }

 settings中配置redis

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://140.143.227.206:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100},
             "PASSWORD": "1234",
        }
    }
}
settings中redis的配置
SHOPPING_CAR_KEY = "luffy_shopping_car_%s_%s"

 url.py

url(r'^shoppingcar/$', shoppingcar.ShoppingCarViewSet.as_view()),

 认证:

class LuffyAuth(BaseAuthentication):

    def authenticate(self, request):
        """
        用户请求进行认证
        :param request:
        :return:
        """
        # http://wwwww...c0ovmadfasd/?token=adfasdfasdf
        token = request.query_params.get('token')
        obj = models.UserAuthToken.objects.filter(token=token).first()
        if not obj:
            raise AuthenticationFailed({'code':1001,'error':'认证失败'})

        return (obj.user.username,obj)
认证

视图,实现增删改查

购物车的实现思路

1.用户选择:课程 价格策略,提交
        2.获取课程 价格策略进行合法校验(数据库)
        3.数据获取,构造结构:
            {
                shopping_car_用户id_课程id:{
                    'title':'',
                     img:'xxx',
                     policy:{
                     },
                     default:''
                }
            
            }
        4. 将数据以字典的形式保存到redis中.
        
    修改:
        1.用户选择:课程 价格策略,提交
        2.获取课程 价格策略进行合法校验(redis查询)
        3.更新
        
    删除:
        1.用户选择:课程 价格策略,提交
        2.获取课程 价格策略进行合法校验(redis查询)
        3.删除
        
    查看:1.构造key_shopping_car_用户ID_*
         2.scan_iter

 

POST请求:购物车中添加一条数据
					  请求体:
						{
							courseid:1,
							policy_id:10
						}
		后台:
			检验当前课程是否有此价格策略,合法:将数据构造字典,再添加到redis

GET请求:查看自己购物车中的所有数据 获取当前登录用户ID,根据用户ID去redis的购物车中获取数据。 DELETE请求:删除购物车中的数据 请求体: { course_ids:[1,2] } PUT/PATCH请求:更新价格策略 请求体: { courseid:1, policy_id:13 }
class ShoppingCarViewSet(APIView):
    authentication_classes = [LuffyAuth,]
    conn = get_redis_connection("default") # 类下的全局 下面用加self

    def post(self, request, *args, **kwargs):
        """
        将课程添加到购物车
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        try:
            # 1. 获取用户提交的课程ID和价格策略ID
            course_id = int(request.data.get('courseid'))
            policy_id = int(request.data.get('policyid'))

            # 2. 获取专题课信息
            course = models.Course.objects.get(id=course_id)

            # 3. 获取该课程相关的所有价格策略
            price_policy_list = course.price_policy.all()
            price_policy_dict = {}
            for item in price_policy_list:
                price_policy_dict[item.id] = {
                    "period":item.valid_period,
                    "period_display":item.get_valid_period_display(),
                    "price":item.price,
                }

            # 4. 判断用户提交的价格策略是否合法
            if policy_id not in price_policy_dict:
                # 价格策略不合法
                raise PricePolicyInvalid('价格策略不合法')

            # 5. 将购物信息添加到redis中
            # self.conn
            # car_key = "luffy_shopping_car_%s_%s"
            car_key = settings.SHOPPING_CAR_KEY %(request.auth.user_id,course_id,)
            car_dict = {
                'title':course.name,
                'img':course.course_img,
                'default_policy':policy_id,
                'policy':json.dumps(price_policy_dict)
            }
            # conn = get_redis_connection("default")
            self.conn.hmset(car_key,car_dict)
            ret.data = '添加成功'

        except PricePolicyInvalid as e:
            ret.code = 2001
            ret.error = e.msg
        except ObjectDoesNotExist as e:
            ret.code = 2001
            ret.error = '课程不存在'
        except Exception as e:
            ret.code = 1001
            ret.error = '获取购物车失败'
        return Response(ret.dict)

    def delete(self, request, *args, **kwargs):
        """
        购物车中删除课程
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        try:
            course_id_list = request.data.get('courseids')
            key_list = [ settings.SHOPPING_CAR_KEY %(request.auth.user_id,course_id,) for course_id in course_id_list]
            self.conn.delete(*key_list)
        except Exception as e:
            ret.code = 1002
            ret.error = "删除失败"

        return Response(ret.dict)

    def patch(self, request, *args, **kwargs):
        """
        修改课程的价格策略
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        try:
            # 1. 获取价格策略ID和课程ID
            course_id = int(request.data.get('courseid'))
            policy_id = str(request.data.get('policyid'))

            # 2. 拼接课程的key
            key = settings.SHOPPING_CAR_KEY %(request.auth.user_id,course_id,)
            if not self.conn.exists(key):
                ret.code = 1002
                ret.error = "购物车中不存在此课程"
                return Response(ret.dict)
            # 3. redis中获取所有的价格策略
            policy_dict = json.loads(str(self.conn.hget(key,'policy'),encoding='utf-8'))
            if policy_id not in policy_dict:
                ret.code = 1003
                ret.error = "价格策略不合法"
                return Response(ret.dict)

            # 4. 在购物车中修改该课程的默认价格策略
            self.conn.hset(key,'default_policy',policy_id)

            ret.data = "修改成功"

        except Exception as e:
            ret.code = 1004
            ret.error = "修改失败"

        return Response(ret.dict)

    def get(self,request, *args, **kwargs):
        """
        查看购物车中所有的商品
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        ret = BaseResponse()
        try:
            key_match = settings.SHOPPING_CAR_KEY %(request.auth.user_id,"*")

            course_list = []

            for key in self.conn.scan_iter(key_match,count=10):
                info = {
                    "title":self.conn.hget(key,'title').decode('utf-8'),
                    "img":self.conn.hget(key,'img').decode('utf-8'),
                    "policy":json.loads(self.conn.hget(key,'policy').decode('utf-8')),
                    "default_policy":self.conn.hget(key,'default_policy').decode('utf-8')
                }
                course_list.append(info)
            ret.data = course_list
        except Exception as e:
            ret.code = 1002
            ret.error = "获取失败"
        return Response(ret.dict)
view.py

 

posted @ 2019-03-10 22:57  离人怎挽_wdj  阅读(244)  评论(0编辑  收藏  举报