# ######################## 深科技相关 ########################
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", } } }
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)