目录
6.4.1、配置redis作为Django缓存和session后端
1、在模板中载入静态文件前需要在配置文件settings.py中加入配置
2、django新版本中查询数据库后对象不存在报错的异常类是core.exceptions的ObjectDoesNotExist
3、加密用户身份信息当做url的token值,用authlib包代替itsdangerous,可以指定签名算法HS256
5、django自带的login()报错:redis输入了一个空类型的值
6、Django的authenticate已经包含了is_active判断,即使用户名密码正确,is_active为0也会返回空,所以需要在setting.py中加配置
7、FastDFS只支持Linux,可以把fastDFS运行在云服务器上,Windows本地电脑上运行FastDFS客户端fdfs-client-py
9、is_authenticated在Django4.0中是一个属性而不是一个方法
10、Django4.0已经移除ungettext,所以在引入haystack的时候会报错,修改haystack文件夹下的admin.py把ungettext三处地方修改为ngettext
11、Django4.0已经移除smart_text,修改haystack文件夹下的form.py俩处地方把smart_text修改为smart_str
13、网站如果想让支付宝平台访问(获取支付后的结果),需要有公网IP
14、安装alipay-sdk-python 提示安装pycrypto 问题:
15、支付宝沙箱测试不需要重新设置密钥和公钥,直接使用默认。
16、使用支付宝交易查询接口要使用AlipayTradeQueryResponse来获取解析后响应的结果
17、win10上没法部署uwsgi,可以通过其它方式间接使用uwsgi,但没必要,最终都是要部署在Linux系统。
19、指定表名,不用一定和应用名相连,class Meta: db_table = '表名'
20、发布网站时需要在settings.py中把debug改为false,allowed_host = ['*']
1、项目来源及开发介绍
修改后的天天生鲜(Django4.0版本):
1.1、天天生鲜介绍
首先,此次天天生鲜项目来源是黑马程序员Python就业班的Web开发项目,虽是几年前的项目,但在Python商城项目里也算是功能比较齐全,什么异步任务处理、页面静态化、搜索引擎、高并发库存问题、邮件发送激活、购物车缓存、分布式文件存储、服务器部署、支付宝支付接口调用这些都有,适合拿来学习Python的Web开发练练手,此篇博客的内容也是我对原先项目笔记的修改,有些图片是原先黑马项目的图片。
其次,原先天天生鲜项目使用的是Django1.8.2版本,我自己改成了新版本Django4.0版本的,使用的虚拟环境是anaconda,不论学习什么语言和框架,一定要会看框架对应的开发文档,从1.8.2到4.0版本的变动挺多的,就需要自己去查看Django4.0的开发文档,附上Django4.0中文的开发文档对应链接:
Django 文档 | Django 文档 | Djangohttps://docs.djangoproject.com/zh-hans/4.0/
最后文末,是我在开发过程中遇到的各种问题,然后我就记了下来,附上了我的解决方法(由于我这个项目是在win10环境下写的,所以遇到的问题会更多。
先上网站运行后截图:
首先是主页:
用户中心的3个功能页面:
购物车页面:
订单支付:
商品详情:
1.2、Web开发流程介绍
在正式学习商城项目开发前,先介绍一下常见Web商城项目的开发流程:
1.2.1、需求分析
1.2.1.1、用户模块
1.注册页
- 注册时校验用户名是否已被注册。
- 完成用户信息的注册。
- 给用户的注册邮箱发送邮件,用户点击邮件中的激活链接完成用户账户的激活。
2.登录页
- 实现用户的登录功能。
3.用户中心
- 用户中心信息页:显示登录用户的信息,包括用户名、电话和地址,同时页面下方显示出用户最近浏览的商品信息。
- 用户中心地址页:显示登录用户的默认收件地址,页面下方的表单可以新增用户的收货地址。
- 用户中心订单页:显示登录用户的订单信息。
4.其他
- 如果用户已经登录,页面顶部显示登录用户的信息。
1.2.1.2、商品相关
1.首页
- 动态指定首页轮播商品信息。
- 动态指定首页活动信息。
- 动态获取商品的种类信息并显示。
- 动态指定首页显示的每个种类的商品(包括图片商品和文字商品)。
- 点击某一个商品时跳转到商品的详情页面。
2.商品详情页
- 显示出某个商品的详情信息。
- 页面的左下方显示出该种类商品的2个新品信息。
3.商品列表页
- 显示出某一个种类商品的列表数据,分页显示并支持按照默认、价格、和人气进行排序。
- 页面的左下方显示出该种类商品的2个新品信息。
4.其他
- 通过页面搜索框搜索商品信息。
1.2.1.3、购物车相关
- 列表页和详情页将商品添加到购物车。
- 用户登录后,首页,详情页,列表页显示登录用户购物车中商品的数目。
- 购物车页面:对用户购物车中商品的操作。如选择某件商品,增加或减少购物车中商品的数目。
1.2.1.4、订单相关
- 提交订单页面:显示用户准备购买的商品信息。
- 点击提交订单完成订单的创建。
- 用户中心订单页显示用户的订单信息。
- 点击支付完成订单的支付。
1.2.2、项目架构概览
1.2.2.1、页面图:
1.2.2.2、功能图:
1.2.2.3、部署图:
1.2.3、SKU与SPU概念
SPU = Standard Product Unit (标准产品单位)
SPU 是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述 了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个 SPU。 例如:iphone7 就是一个 SPU,与商家,与颜色、款式、套餐都无关。
SKU=stock keeping unit(库存量单位)
SKU 即库存进出计量的单位, 可以是以件、盒、托盘等为单位。 SKU 是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。 在服装、鞋类商品中使用最多最普遍。 例如:纺织品中一个 SKU 通常表示:规格、颜色、款式。
2、项目架构
3、数据库表结构
4、用户认证模型
5、类视图
将视图view以类的形式定义
通用类视图基类:
django.views.generic.View ( 与django.views.generic.base.View 是同一个)
urls.py中配置路由使用类视图的as_view()方法
由dispatch()方法具体将请求request分发至对应请求方式的处理方法中(get、post等)
类视图资料:内置基于类的视图 API | Django 文档 | Django
6、用户模块开发
6.1、Django4.0认证系统文档
django-admin 和 manage.py | Django 文档 | Django
方法名 |
备注 |
create_user |
创建用户 |
authenticate |
登录验证 |
login |
记录登录状态 |
logout |
退出用户登录 |
is_authenticated |
判断用户是否登录 |
login_required装饰器 |
进行登录判断 |
6.2、用户注册
6.2.1、django发送邮件
6.2.2、Celery异步任务队列
6.2.2.1、使用
在项目根目录下新建一个celery_task文件夹,文件夹下新建一个task文件:
# 使用celery
from django.core.mail import send_mail
from django.conf import settings
from celery import Celery
import time
from django.template import loader
# 在任务处理者一端加这几句
import os
import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dailyfresh.settings")
django.setup()
from goods.models import GoodsType, IndexGoodsBanner, IndexPromotionBanner, IndexTypeGoodsBanner
# 创建一个Celery类的实例对象
app = Celery('celery_tasks.tasks', broker='redis://mast:yourpassword@127.0.0.1:6379/1') # 使用我本地电脑的redis的1号数据库当做celery的broker,
此段代码在注册视图函数中,异步实现发送邮件功能:
# 发送激活邮件,包含激活链接: http://127.0.0.1:8000/user/active/token值
# 激活链接中需要包含用户的身份信息, 并且要把身份信息进行加密
"""加密用户的身份信息,生成激活token,使用authlib代替itsdangerous"""
data = {'confirm': user.id}
header = {'alg': 'HS256'} # 签名算法
token = jwt.encode(header=header, payload=data, key=settings.SECRET_KEY) # byte类型
token = token.decode()
# 发送邮箱:使用celery异步处理发送邮件,加入到任务队列(broker)中
send_register_active_email.delay(email, username, token)
# 返回应答, 跳转到首页
return redirect(reverse('goods:index'))
6.2.2.2、发出任务
6.2.2.3、启动worker
重新打开一个终端,输入命令celery -A celery_tasks.tasks worker -l info --pool solo
6.3、用户激活
使用authlib加密用户的身份信息,而不是使用原先项目自带的itsdangerous。
authlib的使用:
参考资料:
JSON Web Token (JWT) — Authlib 1.0.1 documentation
6.3.1、加密用户身份信息
from authlib.jose import jwt, JoseError
"""加密用户的身份信息,生成激活token,使用authlib代替itsdangerous"""
data = {'confirm': user.id}
header = {'alg': 'HS256'} # 签名算法
token = jwt.encode(header=header, payload=data, key=settings.SECRET_KEY) # byte类型
token = token.decode()
6.3.2、解密用户身份信息验证
# 进行解密,获取要激活的用户信息
try:
info = jwt.decode(token, settings.SECRET_KEY)
print(info)
# 获取待激活用户的id
user_id = info['confirm']
# 根据id获取用户信息
user = User.objects.get(id=user_id)
user.is_active = 1
user.save()
6.4、用户登录
6.4.1、配置redis作为Django缓存和session后端
django-redis文档:django-redis 中文文档 — Django-Redis 4.7.0 文档
配置:
# Django的缓存配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2", # 使用2号数据库
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD": "yourpassword"
}
}
}
6.4.2、登录判断装饰器login_required
可以在用户模块的地址配置直接使用:
urlpatterns = [
path('register/', RegisterView.as_view(), name='register'), # 使用视图类
re_path(r'active/(?P<token>.*)$', ActiveView.as_view(), name='active'), # 激活用户
path('login/', LoginView.as_view(), name='login'),
path('', UserInfoView.as_view(), name='user'), # 用户信息-中心
re_path(r'order/(?P<page>\d+)$', UserOrderView.as_view(), name='order'), # 用户信息-订单
path('address/', AddressView.as_view(), name='address'), # 用户信息-地址
path('logout/', LogoutView.as_view(), name='logout'), # 用户注销
path('testcelery/', views.testCelery)
# path('', login_required(UserInfoView.as_view()), name='user'), # 用户信息-中心
# path('order/', login_required(UserOrderView.as_view()), name='order'), # 用户信息-订单
# path('address/', login_required(AddressView.as_view()), name='address'), # 用户信息-地址
# path('register', views.register, name='register'),
# path('register_handle', views.register_handle, name='register_handle')
]
或者修改类LoginRequireMixin中的父类的as_view方法:
在setting.py中配置未登录时的跳转:
6.5、用户退出
logout函数清除登录用户的session信息。
6.6、用户地址
模型类和模型管理器类:
6.7、用户个人信息
6.7.1 redis存储历史浏览记录分析
参考资料:
Welcome to redis-py’s documentation! — redis-py dev documentation
6.7.2、django-redis获取redis链接
from django_redis import get_redis_connection
on = get_redis_connection('default') # 使用setting.py中默认的redis配置
7、商品模块开发
7.1、了解FastDFS分布式文件系统
(我个人是把FastDFS部署在自己的阿里云服务器上,安装到云服务器上去访问是也遇到了很多问题,文末总结问题)
集群
启动FastDFS的方法,需要的操作:
修改如下的配置文件 (在/etc/fdfs目录中)
tracker_server=自己的ip地址:22122
启动tracker、storage、nginx服务:
sudo service fdfs_trackerd start
sudo service fdfs_storaged start
sudo /usr/local/nginx/sbin/nginx
执行如下命令测试是否成功
fdfs_upload_file /etc/fdfs/client.conf 要上传的图片文件
如果返回类似group1/M00/00/00/rBIK6VcaP0aARXXvAAHrUgHEviQ394.jpg的文件id则