说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢你们!php
接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/88810060css
目录html
一丶模板文件继承前端
二丶用户中心页面显示python
三丶登陆验证以及登陆后跳转的地址nginx
四丶封装login_required方法redis
六丶用户中心-地址数据库
七丶用户中心-信息django
1.分析网页中共有的模块,定义父模板
{# 首页 注册 登陆 #} <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> {% load staticfiles %} <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> {# 网页标题内容块 #} <title>{% block title %}{% endblock title %}</title> <link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}"> {# 网页顶部引入文件块 #} {% block topfiles %}{% endblock topfiles %} </head> <body> {# 网页顶部欢迎信息块 #} {% block header_con %} <div class="header_con"> <div class="header"> <div class="welcome fl">欢迎来到每天生鲜!</div> <div class="fr"> <div class="login_info fl"> 欢迎您:<em>张 山</em> </div> <div class="login_btn fl"> <a href="login.html">登陆</a> <span>|</span> <a href="register.html">注册</a> </div> <div class="user_link fl"> <span>|</span> <a href="../static/user_center_info.html">用户中心</a> <span>|</span> <a href="../static/cart.html">个人购物车</a> <span>|</span> <a href="../static/user_center_order.html">个人订单</a> </div> </div> </div> </div> {% endblock header_con %} {# 网页顶部搜索框块 #} {% block search_bar %} <div class="search_bar clearfix"> <a href="index.html" class="logo fl"><img src="{% static 'images/logo.png' %}"></a> <div class="search_con fl"> <input type="text" class="input_text fl" name="" placeholder="搜索商品"> <input type="button" class="input_btn fr" name="" value="搜索"> </div> <div class="guest_cart fr"> <a href="#" class="cart_name fl">个人购物车</a> <div class="goods_count fl" id="show_count">1</div> </div> </div> {% endblock search_bar %} {# 网站主体内容块 #} {% block body %}{% endblock body %} <div class="footer"> <div class="foot_link"> <a href="#">关于咱们</a> <span>|</span> <a href="#">联系咱们</a> <span>|</span> <a href="#">招聘人才</a> <span>|</span> <a href="#">友情连接</a> </div> <p>CopyRight © 2016 北京每天生鲜信息技术有限公司 All Rights Reserved</p> <p>电话:010-****888 京ICP备*******8号</p> </div> {# 网页底部html元素块 #} {% block bottom %}{% endblock bottom %} {# 网页底部引入文件块 #} {% block bottomfiles %}{% endblock bottomfiles %} </body> </html>
{# 详情页 列表页 #} {% extends 'base.html' %} {# 网站主体内容块 #} {% block body %} <div class="navbar_con"> <div class="navbar clearfix"> <div class="subnav_con fl"> <h1>所有商品分类</h1> <span></span> <ul class="subnav"> <li><a href="#" class="fruit">新鲜水果</a></li> <li><a href="#" class="seafood">海鲜水产</a></li> <li><a href="#" class="meet">猪牛羊肉</a></li> <li><a href="#" class="egg">禽类蛋品</a></li> <li><a href="#" class="vegetables">新鲜蔬菜</a></li> <li><a href="#" class="ice">速冻食品</a></li> </ul> </div> <ul class="navlist fl"> <li><a href="">首页</a></li> <li class="interval">|</li> <li><a href="">手机生鲜</a></li> <li class="interval">|</li> <li><a href="">抽奖</a></li> </ul> </div> </div> {# 详情页,列表页主体内容块 #} {% block main_content %}{% endblock main_content %} {% endblock body %}
{# 购物车 提交订单 #} {% extends 'base.html' %} {% load staticfiles %} {# 网页顶部搜索框块 #} {% block search_bar %} <div class="search_bar clearfix"> <a href="index.html" class="logo fl"><img src="{% static 'images/logo.png' %}"></a> <div class="sub_page_name fl">| {% block page_title %}{% endblock page_title %}</div> <div class="search_con fr"> <input type="text" class="input_text fl" name="" placeholder="搜索商品"> <input type="button" class="input_btn fr" name="" value="搜索"> </div> </div> {% endblock search_bar %}
{# 用户中心3页面 #} {% extends 'base_no_cart.html' %} {% block title %}每天生鲜-用户中心{% endblock title %} {% block page_title %}用户中心{% endblock page_title %} {% block body %} <div class="main_con clearfix"> <div class="left_menu_con clearfix"> <h3>用户中心</h3> <ul> <li><a href="user_center_info.html" class="active">· 我的信息</a></li> <li><a href="user_center_order.html">· 所有订单</a></li> <li><a href="user_center_site.html">· 收货地址</a></li> </ul> </div> {# 用户中心右侧内容块 #} {% block right_content %}{% endblock right_content %} </div> {% endblock body %}
2.注册页登陆页主页继承于父模板
3.用户中心三个页面继承于父模板
4.购物车页提交订单页继承于父模板
5.商品详情页商品列表页继承于父模板
1.定义类视图
# /user class UserInfoView(View): """用户中心-信息""" def get(self, request): """显示页面""" return render(request, "user_center_info.html")
class UserOrderView(View): """用户中心-订单""" def get(self, request): """显示页面""" return render(request, "user_center_order.html")
# /user/address class UserAddressView(View): """用户中心-地址""" def get(self, request): """显示页面""" return render(request, "user_center_site.html")
2.在df_user/urls中配置路由
url(r"^$", UserInfoView.as_view(), name="user"), # 用户中心-信息 url(r"^order$", UserOrderView.as_view(), name="order"), # 用户中心-订单 url(r"^address$", UserAddressView.as_view(), name="address"), # 用户中心-地址
3.输入路由地址进行页面显示
4.修改用户中心连接地址以及激活active选择器
<li><a href="{% url 'user:user' %}" class="active">· 我的信息</a></li> <li><a href="{% url 'user:order' %}">· 所有订单</a></li> <li><a href="{% url 'user:address' %}">· 收货地址</a></li>
return render(request, "user_center_info.html", {"page":"user"}) return render(request, "user_center_info.html", {"page":"order"}) return render(request, "user_center_info.html", {"page":"address"})
<ul> <li><a href="{% url 'user:user' %}" {% if page == 'user' %}class="active"{% endif %}>· 我的信息</a></li> <li><a href="{% url 'user:order' %}"{% if page == 'order' %}class="active"{% endif %}>· 所有订单</a></li> <li><a href="{% url 'user:address' %}"{% if page == 'address' %}class="active"{% endif %}>· 收货地址</a></li> </ul>
1.登陆验证
from django.contrib.auth.decorators import login_required
url(r"^$", login_required(UserInfoView.as_view()), name="user"), # 用户中心-信息
说明:这里之因此换了个浏览器是由于以前的谷歌浏览器有登陆成功保存的session,博主不想清除浏览缓存
2.登陆成功后跳转的地址
next_url = request.GET.get("next", reverse("goods:index")) response = redirect(next_url)
url(r"^order$", login_required(UserOrderView.as_view()), name="order"), # 用户中心-订单 url(r"^address$", login_required(UserAddressView.as_view()), name="address"), # 用户中心-地址
1.定义工具类
from django.contrib.auth.decorators import login_required # 验证是否登陆 class LoginRequiredMixin(object): @classmethod def as_view(cls, **initkwargs): view = super(LoginRequiredMixin, cls).as_view(**initkwargs) return login_required(view)
2.在用户中心类视图中继承LoginRequiredMixin类并在urls中去掉login_required方法
url(r"^$", UserInfoView.as_view(), name="user"), # 用户中心-信息 url(r"^order$", UserOrderView.as_view(), name="order"), # 用户中心-订单 url(r"^address$", UserAddressView.as_view(), name="address"), # 用户中心-地址
1.登陆后显示用户名不显示登陆注册功能选项
{% if user.is_authenticated %} <div class="login_btn fl"> 欢迎您:<em style="color: #f89752">{{ user.username }}</em> </div> {% else %} <div class="login_btn fl"> <a href="/user/login">登陆</a> <span>|</span> <a href="/user/register">注册</a> </div> {% endif %}
2.退出登陆
<div class="login_btn fl"> <span>|</span> <a href="{% url 'user:logout' %}">退出</a> </div>
# /user/logout class LogoutView(View): """退出""" def get(self, request): logout(request) # 退出后跳转到主页 return redirect(reverse("goods:index"))
url(r"^logout$", LogoutView.as_view(), name="logout"), # 注销
3.验证登陆登出功能
1.在UserAddressView类中定义post方法添加地址
receiver = request.POST.get("receiver") # 收件人 addr = request.POST.get("addr") # 地址 zip_code = request.POST.get("zip_code") # 邮编 phone = request.POST.get("phone") # 手机号
if not all([receiver, addr, phone]): return render(request, "user_center_site.html", {"error_msg":"数据不完整"})
if not re.match(r'^1[3|4|5|7|8|9][0-9]{9}$', phone): return render(request, "user_center_site.html", {"error_msg": "手机号格式不正确"})
user = request.user try: address = Address.objects.get(user=user, is_default=True) except Address.DoesNotExist: # 出现异常表示该用户尚未设置默认地址 address = None if address: is_default = False else: is_default = True
Address.objects.create(user=user, receiver=receiver, addr=addr, zip_code=zip_code, phone=phone, is_default=is_default) return redirect(reverse("user:address"))
2.在UserAddressView类get方法中获取地址类Address对象
def get(self, request): """显示页面""" # 获取用户的的收货地址 user = request.user try: address = Address.objects.get(user=user, is_default=True) except Address.DoesNotExist: # 出现异常表示该用户尚未设置默认地址 address = None return render(request, "user_center_site.html", {"page":"address","address":address})
<div class="site_con"> <dl> <dt>当前地址:</dt> {% if address %} <dd>{{ address.addr }} ({{ address.receiver }} 收) {{ address.phone }}</dd> {% else %} <dd style="color: red">无默认地址</dd> {% endif %} </dl> </div>
3.测试
4.定义地址模型类管理器
class AddressManager(models.Manager): """地址模型类管理器""" # 用于操做模型类对应的数据表 def get_default_address(self, user): try: address = self.get(user=user, is_default=True) except self.model.DoesNotExist: # 出现异常表示该用户尚未设置默认地址 address = None return address
objects = AddressManager()
address = Address.objects.get_default_address(user)
说明:收货地址栏能够添加一个复选框,在这个复选框中显示出该用户全部的收货地址,当选择某一个收货地址时,则设置改收货地址的is_default值为1
1.显示基本信息
def get(self, request): """显示页面""" # 获取用户地址信息 user = request.user address = Address.objects.get_default_address(user) return render(request, "user_center_info.html", {"page":"user", "address":address})
<ul class="user_info_list"> <li><span>用户名:</span>{{ user.username }}</li> {% if address %} <li><span>联系方式:</span>{{ address.phone }}</li> <li><span>联系地址:</span>{{ address.addr }}</li> {% else %} <li><span>联系方式:</span>无</li> <li><span>联系地址:</span>无</li> {% endif %} </ul>
2.获取用户历史浏览记录
1.何时添加历史浏览记录 当用户点击进入某个商品详情页时,须要添加历史浏览记录 2.何时获取历史浏览记录 在用户信息页面显示 3.历史浏览记录往哪里存储 存储在内存级的redis数据库中提升读写效率 4.以哪一种数据格式进行存储 以list数据格式进行存储
conn = get_redis_connection("default")
history_key = "history_%d" % user.id
sku_ids = conn.lrange(history_key, 0 ,4)
goods_list = [] for sku_id in sku_ids: goods = GoodsSKU.objects.get(id=sku_id) goods_list.append(goods)
content = {"page":"user", "address":address, "goods_list":goods_list } return render(request, "user_center_info.html", content )
{% for goods in goods_list %} <li> <a href="detail.html"><img src="{{ goods.image.url }}"></a> <h4><a href="detail.html">{{ goods.name }}</a></h4> <div class="operate"> <span class="prize">¥{{ goods.price }}</span> <span class="unit">{{ goods.price }}/{{ goods.unite }}</span> <a href="#" class="add_goods" title="加入购物车"></a> </div> </li> {% empty %} 无历史浏览记录 {% endfor %}
1.FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题
2.该项目之因此使用FastDFS进行图片存储,而不使用django管理员网页进行上传,是由于使用FastDFS对海量存储以及存储扩容方便,同时也解决了同文件重复的问题
3.FastDFS架构图
服务端两个角色:
Tracker:管理集群,tracker 也能够实现集群。每一个 tracker 节点地位平等。收集 Storage 集群的状态。
Storage:实际保存文件 Storage 分为多个组,每一个组之间保存的文件是不一样的。每 个组内部能够有多个成员,组成员内部保存的内容是同样的,组成员的地位是一致的,没有 主从的概念。
4.文件上传流程
说明:客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于之后访问该文 件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名
组名:文件上传后所在的 storage 组名称,在文件上传成功后有 storage 服务器返回, 须要客户端自行保存。
虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项 store_path*对应。若是配置了 store_path0 则是 M00,若是配置了 store_path1 则是 M01,以此类推。
数据两级目录:storage 服务器在每一个虚拟磁盘路径下建立的两级目录,用于存储数据 文件。
文件名:与文件上传时不一样。是由存储服务器根据特定信息生成,文件名包含:源存储 服务器 IP 地址、文件建立时间戳、文件大小、随机数和文件拓展名等信息
5.文件下载流程
6.开发环境搭建简易FastDFS架构
7.FastDFS安装
说明:FastDFS须要在Linux系统进行安装,网上查了资料并无推出能够在Windows环境下安装的FastDFS版本,安装FastDFS以前需安装fastdfs依赖包libfastcommon-master.zip
8.配置跟踪服务器tracker
sudo cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
sudo vim /etc/fdfs/tracker.conf
9.配置存储服务器storage
sudo cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
sudo vim /etc/fdfs/storage.conf
base_path=/home/taogang/fastdfs/storage store_path0=/home/taogang/fastdfs/storage tracker_server=你的ubuntu虚拟机的ip地址:22122
10.启动tracker 和 storage
sudo service fdfs_trackerd start sudo service fdfs_storaged start
11.测试是否安装成功
sudo cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
sudo vim /etc/fdfs/client.conf
base_path=/home/taogang/fastdfs/tracker tracker_server=你的ubuntu虚拟机的ip地址:22122
1.说明:使用FastDFS分布式系统架构在用户量比较大的时候,用户对内容的获取效率是很是低的,为了提升效率须要借助Nginx服务器来配置FastDFS进行使用,Nginx服务器在处理静态文件的效率是很高的,由于Nginx服务器内核是epoll,上传资源使用fdfs系统,获取资源则借助nginx服务器来获取;需安装nginx-1.8.1.tar.gz和fastdfs-nginx-module-master.zip这两个包,fastdfs-nginx-module-master.zip这个包的做用就是让nginx服务器和fdfs系统进行关联配置的做用
2.安装nginx和fastdfs-nginx-module
结果报错了,看提示是缺乏PCRE库
sudo apt-get update sudo apt-get install libpcre3 libpcre3-dev sudo apt-get install openssl libssl-dev
sudo vim /etc/fdfs/mod_fastdfs.conf
connect_timeout=10 # 链接fdfs超时时间 tracker_server=本身ubuntu虚拟机的ip地址:22122 url_have_group_name=true # 访问fdfs时带不带组的信息(group1) store_path0=/home/python/fastdfs/storage
sudo vim /usr/local/nginx/conf/nginx.conf
3.测试Nginx服务器配合FastDFS系统进行文件上传与获取