說明:該篇博客是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝你們!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系統進行文件上傳與獲取