刨析django----阶段项目2

天天生鲜

项目开发流程

B2B,商业对商业的电子商务模式
C2C,消费者个人对个人
B2C,商户对个人,如天天生鲜(Business to Customer)
C2B,个人对企业,个人提出需求,交给企业完成
O2O,线上到线下,如美团
F2C,工厂到个人
B2B2C,商业对商业对个人,如京东、淘宝

项目立项,确定做这个项目
需求分析,功能需求分析,可行性分析
原型设计,磨刀
后端架构设计(模块划分、技术选择)、前端UI设计、页面设计
详细设计,各个功能模块划分及可行性
数据库设计,表、字段、关系
编码实现(git)、单元测试
代码整合
集成测试
上线发布

可行性分析

现在的web系统开发已经相当成熟,技术上可以采用java/python的生态圈实现一个前后端交互的超市系统。
后端再搭配一些机器学习算法实现商品的智能推荐。

开发环境

python 3.6
django2.2.12
mysql-5.7
vscode

相关技术分析

  1. haystack+whoosh
    配置全文索引
  2. django-redis
    配置内存缓存
  3. alipay-sdk-python
    支付宝付款API
    支付宝官网

需求分析

用户模块

  1. 注册页面
    用户名唯一,密码满足复杂度,邮箱符合规范,注册完成向用户邮箱发送激活链接,用户点击链接实现激活账号。

  2. 登录页,使用用户名、密码登录;后端验证、会话保持session&Cookie

  3. 用户中心
    信息页,显示用户的信息,姓名、电话、地址、最近浏览的信息;
    地址页,显示默认的收货地址、添加收获地址功能
    订单页,显示订单信息
    页面顶部,显示已经登录的用户信息
    在这里插入图片描述

商品模块

  1. index.html,网站的首页,动态轮播图(展示推荐商品)
    动态指定信息类别(点击跳到对应的锚点)、推荐类别(点击进入详情页)
    在这里插入图片描述
    轮播图展示推荐,活动页展示活动产品
    在这里插入图片描述

  2. list.html,商品列表页
    按照类别显示商品

  3. detail.html,商品详情页,一个商品的详细信息,可以加入购物车

    搜索框,顶部显示,可以 关键字 搜索商品

购物车模块

  1. 首页展示我的购物车,页面跳转此部分不变(作为父模板)
    在这里插入图片描述

  2. 点击商品列表项目,进入详情页,然后可以加入购物车
    在这里插入图片描述

  3. 用户登录后,购物车显示加入的商品数

  4. 购物车页面car.html, 显示加入商品的信息
    在这里插入图片描述

订单模块

  1. 提交订单页面,显示将要购买的商品信息及支付方式
    在这里插入图片描述
  2. 点击 ‘提交订单’,创建订单
  3. 用户中心的订单页面显示用户的全部订单,点击支付完成付款
    在这里插入图片描述

概要设计

系统架构设计----页面
在这里插入图片描述
系统架构设计----功能

在这里插入图片描述
系统结构设计----部署
在这里插入图片描述

总体架构:
在这里插入图片描述
mysql, web应用普遍使用的关系数据库,数据量达到亿级别时,检索性能下降,无法很好地应对高并发的压力。
缓存服务器,将经常用到的数据存储在缓存中,减少对mysql数据库的访问,分担数据库的压力。常用redis(缓存数据、session数据),使用python中的redis模块连接redis-server.
celery,异步处理库,处理一些耗时的操作(pip3 install celery)
fastdfs,分布式文件存储系统,django自带的图片上传功能,面对大量数据时,效率不高,所以使用fastdfs。

详细设计

用户模块

采用Django自带的认证系统,继承AbstractUser类,扩展模型类的字段,创建普通用户、管理员用户
使用内建的authenticate 验证用户的登录
使用内建的loginlogout 实现用户的登录、登出
使用内建的login_required检测用户的登录
Redis实现对session的缓存,
邮件采用Django内置的send_mail()函数
采用celery实现异步请求,发送邮件
历史浏览记录使用Redis的list作为记录

  1. 创建user应用
    所有应用可以放入一个文件夹apps,然后从文件夹下安装和导入。
#创建应用
python3 manage.py startapp user
#安装应用 settings.py > INSTALLED_APPS > apps.user

#创建模型类User, 继承auth应用的AbstractUser
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer #序列化对象
from db.base_model import BaseModel  #自定义的基类 created_time/updated_time/is_delete 字段

class User(AbstractUser, BaseModel): #BaseModel 自定义的时间基类
    '''用户模型类'''
    #username、password、email 类属性
    #is_active/is_superuser
    #直接继承AbstractUser
    def generate_active_token(self):
        '''生成 用户签名  字符串'''
        serializer = Serializer(settings.SECRET_KEY, 3600)
        info = {'confirm': self.id}
        token = serializer.dumps(info) #序列化为字节串
        return token.decode()

    class Meta:
        db_table = 'df_user'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

# 创建Address模型类
from django.db import models
#自定义一个对象管理器,类似的objects
class AddressManager(models.Manager):
	#自定义一个方法
	def get_default_address(self, user):
		#self is objects
		try:
			address = self.get(user=user, is_default=True)
		except self.model.DoesNotExist as e:
			address = None
		return address
		
class Address(BaseModel): #BaseModel已经继承models.Model
    """收件地址模型类"""
    user = models.ForeignKey('User', on_delete=models.CASCADE, verbose_name='所属用户')
    receiver = models.CharField(max_length=20, verbose_name='收件人')
    addr = models.CharField(max_length=256, verbose_name='收货地址')
    zip_code = models.CharField(max_length=6, null=True, verbose_name='邮政编码')
    phone = models.CharField(max_length=11, verbose_name='联系电话')
    is_default = models.BooleanField(default=False, verbose_name='是否默认')

    # 自定义一个模型管理器对象, 使用当前对象管理器操作数据
    objects = AddressManager()

    class Meta:
        db_table = 'df_address'  #数据库中的表名
        verbose_name = '地址'    #后台管理的表名
        verbose_name_plural = verbose_name  #表名为单数形式

# 迁移模型类
python3 manage.py makemigrations
python3 manage.py migrate
  1. 注册子功能
    路由:/user/register ; 注意最后没有/
    GET 请求,返回register.html
    POST请求,提交注册数据

视图类,RegisterView(View)

from django.views.generic import View

class RegisterView(View):
	def get(self,request):
		return render(request, 'register.html') #所有的页面放/templates
	def post(self, request):
        # 接受前端提交的数据,进行注册
        username = request.POST.get('user_name')
        password = request.POST.get('pwd') #
        email = request.POST.get('email')
        allow = request.POST.get('allow')
		
  1. 登录子功能

  2. 用户中心子功能

商品模块

采用MySQL数据库存储,自定义模型类
django-haystack+whoosh实现对中文商品名字的检索(全文索引)
Nginx+fastdfs实现对图片的存储

  1. 创建goods应用
#创建应用
python3 manage.py startapp goods

#安装应用  settings.py > INSTALLED_APPS > apps.goods

#创建模型类
class GoodsType(BaseModel):
    """商品类型  模型类"""
    name = models.CharField(max_length=20, verbose_name='种类名称')
    #前端通过class属性指定logo,所以这里的logo值为字符串
    logo = models.CharField(max_length=20, verbose_name='标识')
    #用户上传图片,在根目录下的type目录
    image = models.ImageField(upload_to='type', verbose_name='商品类型图片')

    class Meta:
        db_table = 'df_goods_type'
        verbose_name = '商品种类'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class GoodsSPU(BaseModel):
    """
        商品SPU模型类
        标准产品单位,如iPhone13,与颜色、尺寸等无关
    """
    name = models.CharField(max_length=20, verbose_name='商品SPU名称')
    detail = HTMLField(blank=True, verbose_name='商品详情')

    class Meta:
        db_table = 'df_goods_spu'
        verbose_name = '商品SPU'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

class GoodsSKU(BaseModel):
    """
        商品SKU模型类
        标准库存单位,与产品属性有关
    """
    status_choices = (
        (0, '下线'),
        (1, '上线'),
    )

    type = models.ForeignKey('GoodsType', on_delete=models.CASCADE, verbose_name='商品种类')
    goods_spu = models.ForeignKey('GoodsSPU',on_delete=models.CASCADE, verbose_name='商品SPU')
    name = models.CharField(max_length=20, verbose_name='商品名称')
    desc = models.CharField(max_length=256, verbose_name='商品简介')
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='商品价格')
    unit = models.CharField(max_length=30, verbose_name='商品单位')
    image = models.ImageField(upload_to='goods', verbose_name='商品图片')
    stock = models.IntegerField(default=1, verbose_name='商品库存')
    sales = models.IntegerField(default=0, verbose_name='商品销量')
    status = models.SmallIntegerField(default=1, choices=status_choices, verbose_name='商品状态')


    class Meta:
        db_table = 'df_goods_sku'
        verbose_name = '商品'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class GoodsImage(BaseModel):
    """商品图片模型类"""
    sku = models.ForeignKey('GoodsSKU', on_delete=models.CASCADE, verbose_name='商品')
    image = models.ImageField(upload_to='goods', verbose_name='图片路径')

    class Meta:
        db_table = 'df_goods_image'
        verbose_name = '商品图片'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.sku.name


class IndexGoodsBanner(BaseModel):
    """首页轮播商品展示模型类"""
    sku = models.ForeignKey('GoodsSKU', on_delete=models.CASCADE, verbose_name='商品')
    image = models.ImageField(upload_to='banner', verbose_name='图片')
    index = models.SmallIntegerField(default=0, verbose_name='展示顺序')

    class Meta:
        db_table = 'df_index_banner'
        verbose_name = '首页轮播图片'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.sku.name


class IndexTypeGoodsBanner(BaseModel):
    """首页分类商品展示模型类"""
    DISPLAY_TYPE_CHOICES = (
        (0, '标题'),
        (1, '图片'),
    )
    type = models.ForeignKey('GoodsType', on_delete=models.CASCADE, verbose_name='商品类型')
    sku = models.ForeignKey('GoodsSKU', on_delete=models.CASCADE, verbose_name='商品')
    display_type = models.SmallIntegerField(default=1, choices=DISPLAY_TYPE_CHOICES, verbose_name='商品显示方式')
    index = models.SmallIntegerField(default=0, verbose_name='展示顺序')

    class Meta:
        db_table = 'df_index_type_goods'
        verbose_name = '主页分类展示商品'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.sku.name

class IndexPromotionBanner(BaseModel):
    """首页促销活动模型类"""
    url = models.CharField(max_length=256, verbose_name='活动链接')
    name = models.CharField(max_length=20, verbose_name='活动名称')
    image = models.ImageField(upload_to='goods', verbose_name='图片路径')
    index = models.SmallIntegerField(default=0, verbose_name='展示顺序')

    class Meta:
        db_table = 'df_index_promotion'
        verbose_name = '主页促销活动'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

购物车模块

订单模块

使用MySQL事务,对一组sql操作进行提交或者撤销,使用悲观锁处理订单并发效果。

数据库设计

  1. 用户表
    在这里插入图片描述

  2. 用户收件地址表
    在这里插入图片描述

  3. 商品SKU表
    在这里插入图片描述

  4. 商品种类表
    在这里插入图片描述

  5. 商品图片表
    在这里插入图片描述

  6. 商品SPU表
    在这里插入图片描述
    SPU = Standard Product Unit,标准产品单位
    属性值、特性相同的商品即可称为一个SPU。如颜色、款式、套餐无关
    如迷你香蕉、红富士苹果、iphone7等

SKU = Stock Keep Unit (库存量单位)
库存进出计量单位,如一捆、一箱、1kg等单位,物理上不可分割的最小存货单元。

  1. 轮播图数据表
    在这里插入图片描述

  2. 促销活动表
    在这里插入图片描述

  3. 商品列表项 数据表
    在这里插入图片描述
    在这里插入图片描述

  4. 订单信息表
    在这里插入图片描述

  5. 订单商品表
    在这里插入图片描述

redis,实现购物车、用户最近浏览记录
持久化?

编码实现

参考详细设计中的代码

效果展示

总结

参考文献

天天生鲜项目

 
 
 
 
上一篇:刨析django----Nginx反向代理    下一篇:刨析django----配置全文索引

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值