1 需求分析
github源碼:https://www.github.com/wangyingchuang/dailyfresh
1.1 用戶模塊
1) 注冊頁
l 注冊時校驗用戶名是否已被注冊。
l 完成用戶信息的注冊
l 給用戶的注冊郵箱發送郵件,用戶點擊郵件中的激活鏈接完成用戶賬戶的激活。
2)登陸頁
l 實現用戶的登錄功能
3)用戶中心
l 用戶中心信息頁,顯示登錄用戶的信息,包括用戶名、電話和地址,同時頁面下方顯示出用戶最近瀏覽的商品信息。
l 用戶中心地址頁:顯示登陸用戶的默認收件地址,頁面下方的表單可以新增用戶的收貨地址。
l 用戶中心訂單頁:顯示登錄用戶的訂單信息。
4)其他
l 如果用戶已經登陸,頁面頂部顯示用戶的訂單信息。
1.2 商品模塊
1)首頁
l 動態指定首頁輪播商品信息。
l 動態指定首頁活動信息。
l 動態獲取商品的種類信息並顯示。
l 動態指定首頁顯示的每個種類的商品(包括圖片商品的文字商品)。
l 點擊某一個商品時跳轉到商品的詳情頁面。
2)商品詳情頁
l 顯示出某個商品的詳細信息。
l 頁面下方顯示出該商品的兩個新品信息。
3)商品列表頁
l 顯示出某一個種類的商品的列表數據,分頁顯示並支持按照默認、價格和人氣進行排序。
l 頁面下方顯示出該商品的兩個新品信息。
4)其他
l 通過搜索框搜索商品信息。
1.3 購物車模塊
l 列表頁和詳情頁將商品添加到購物車。
l 用戶登錄后,首頁,詳情頁,列表頁顯示用戶購物車中的商品數目。
l 購物車頁面:對用戶購物車中的商品操作。如選擇某件商品,增加或減少購物車中的商品數目。
1.4 訂單相關
l 提交訂單頁面:顯示用戶准備購買的商品信息。
l 點擊提交訂單完成訂單的創建。
l 用戶中心訂單頁顯示用戶的訂單信息。
l 點擊支付完成訂單的支付。
l 點擊評價完成訂單的評價。
2 項目架構概覽
2.1 頁面圖
2.2 功能圖
2.3 部署圖
3 數據庫設計
3.1 實體類圖
4 開發環境和工具
ubuntu18.4
python>3.6
Django == 2.2
pychram
redis
mysql 5.7
celery
fastDFS
nginx
Django-haystack
whoosh
jieba
alipay
requests
5 配置項目環境
5.1 配置mysql數據庫環境
5.2 配置緩存路徑--redis數據庫環境
緩存存到redis數據庫里
5.3 配置session存儲方式
存到緩存
5.4 發送郵件配置
5.5 配置fastDFS 和 nginx
參考https://blog.csdn.net/weixin_42149982/article/details/82391218
l 與python進行交互
Dailyfresh/settings.py
Utils/fast/storage.py
5.6 配置celery
Celery_tasks/tasks.py
Celery 官網:http://www.celeryproject.org
Celery 官方文檔英文版:http://docs.celeryproject.org/en/latest/index.html
Celery 官方文檔中文版:http://docs.jinkan.org/docs/celery
celery配置:http://docs.jinkan.org/docs/celery/configuration.html#configuration
啟動celery
Celery -A celery_task.tasks worker -l info
5.7 配置Django-haystack + whoosh + jieba
詳細步驟:https://blog.csdn.net/abc_soul/article/details/88641269
Pip3 install Django-haystack
Pip3 install whoosh
Pip3 install jieba
首先是把 django haystack 加入到 INSTALLED_APPS 選項里,再添加配置, django haystack 規定。要相對某個 app 下的數據進行全文檢索,就要在該 app 下創建一個 search_indexes.py 文件,然后創建一個 XXIndex 類(XX 為含有被檢索數據的模型,如這里的 Test),並且繼承 SearchIndex 和 Indexable。我們使用數據模板去建立搜索引擎索引的文件,接下來就是配置 URL,修改一下搜索表單,讓它提交數據到 django haystack 搜索視圖對應的 URL,使用 Whoosh 作為搜索引擎, haystack_search 視圖函數會將搜索結果傳遞給模板 search/search.html,因此創建這個模板文件,對搜索結果進行簡單渲染,但在 django haystack 中為 Whoosh 指定的分詞器是英文分詞器,可能會使得搜索結果不理想,我們把這個分詞器替換成 jieba 中文分詞器,最后一步就是建立索引文件了,運行命令 python manage.py rebuild_index 就可以建立索引文件了。
5.8 其他配置
l 配置templates路徑
l 配置static路徑
l 配置django認證系統使用的模型類
l 配置 富文本編輯器
注冊應用 ‘tinymce’
l 配置LOGIN_URL
LOFGIN_URL = '/user/login'
l 配置alipay
Pip3 insatll alipay-sdk-python
使用openssl生成本機的公鑰和私鑰。
創建應用
alipay_client_config = AlipayClientConfig()
alipay_client_config.server_url = 'https://openapi.alipaydev.com/gateway.do'
alipay_client_config.app_id = '2016100100641374'
app_private_key = ''
with open(os.path.join(settings.BASE_DIR, 'apps/order/app_private_key.pem'), 'r') as f:
for line in f:
app_private_key += line
alipay_client_config.app_private_key = app_private_key
alipay_public_key = ''
with open(os.path.join(settings.BASE_DIR, 'apps/order/alipay_public_key.pem'), 'r') as f:
for line in f:
alipay_public_key += line
alipay_client_config.alipay_public_key = alipay_public_key
"""
得到客戶端對象。
注意,一個alipay_client_config對象對應一個DefaultAlipayClient,定義DefaultAlipayClient對象后,alipay_client_config不得修改,如果想使用不同的配置,請定義不同的DefaultAlipayClient。
logger參數用於打印日志,不傳則不打印,建議傳遞。
"""
client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)
total_pay = order.transit_price + order.total_price
total_pay = round(float(total_pay), 2)
model = AlipayTradePagePayModel()
model.out_trade_no = order_id
model.total_amount = total_pay
model.subject = "天天生鮮{0}".format(order_id)
model.product_code = "FAST_INSTANT_TRADE_PAY"
調用網頁支付接口
request = AlipayTradePagePayRequest(biz_model=model)
response = client.page_execute(request, http_method="GET")
# 訪問支付頁面
return JsonResponse({'res': 3, 'response': response})
調用查詢交易接口
# request = AlipayTradeQueryRequest(biz_model=model)
# response = client.page_execute(request, http_method="GET")
# data = requests.get(response)
# print(json.loads(data.text))
# data = json.loads(data.text)
# print(data.get('alipay_trade_query_response').get('code'))
6 建立數據模型
l 建立模型類
(依據上面實體類圖創建的,列屬性參照上面即可,具體請看源碼)
user/models.py
Address
User繼承djaong用戶管理模型 ,配置django認證系統使用的模型類
AUTH_USER_MODEL = 'user.User'
Goods/models.py
GoodsType
GoodsSKU
GoodsSPU
GoodsImage
IndexGoodsTypeBanner
IndexGoodsBanner
IndexPromotionBanner
Ordre/models.py
OrderInfo
OrderGoods
7 詳細過程
7.1 用戶模塊設計——user
l 注冊過程
瀏覽器訪問注冊頁面get方式,views.register進行處理(改為views.RegisterView.post),返回注冊頁面。用戶輸入信息進行注冊,瀏覽器提交post請求,views.register進行處理(改為views.RegisterView.post),校驗用戶輸入信息是否合法,將用戶添加到數據庫中,生成用戶token,給用戶發送專屬激活鏈接,用戶點擊鏈接激活,用戶賬戶生效。
生成token使用itsdangerous 模塊中的Timed。。。Serializer加密類,發送郵件使用Django中sender_mail()方法,由於發送郵件過程可能耗時,使用了celery模塊,因此注冊之后頁面直接跳轉到首頁。
l 登陸過程
Get方式:顯示登陸頁面,判斷request.COOKIES是否存在用戶名,存在就自動填充到輸入框。
Post方式:用戶填完登陸信息提交Post表單,此時驗證填入信息是否有誤,如果有誤給出相應提示,用戶賬戶密碼校驗使用了django的authenticate()方法,正確返回一個user對象,並使用login(request, user)記錄用戶的登陸session信息,否則返回None。
有些網頁需要用戶登陸才能訪問,就需要使用login_required()裝飾器裝飾那些也面的View.as_view()方法,此方法如果校驗失敗會自動轉到一個url地址,我在settings.py 配置LOGIN_URL修改它默認的跳轉地址為’/user/login’返回登陸頁面,而且訪問url地址后面自動添加一個get值(’next’),記錄從哪個網頁跳轉過來的,在正確登陸之后可以跳轉到上一個地址。 由於這樣會使urls.py看起來繁雜,創建一個utils/mixin.py
讓需要此功能的View類繼承此類即可,一定要在models.View類之前。
l 退出登錄
Get請求:使用logout()清除用戶的session信息,返回首頁。
l 用戶中心——地址頁
Get請求:獲取用戶的默認地址,返回地址頁。獲取用戶的默認地址多次用到,address=Address.objects.get(user=user, is_default=True), 將此方法封裝,建立一個新的地址管理類繼承model.Manage,寫一個獲取默認地址的方法,再讓Address類的objects=這個類的對象。
Post請求:用戶添加地址,判斷輸入信息是否合法,如果用戶沒有默認地址,則將此地址設為默認地址,跳轉回此頁面。
l 用戶中心——信息頁
Get請求:獲取用戶的默認地址,獲取用戶的最近5條瀏覽的商品圖片,獲取默認地址功能已經實現,獲取用戶最近瀏覽記錄需要使用redis存儲的緩存,用戶在商品頁面瀏覽時添加商品id到redis,在此頁面從redis中讀取商品id再使用模型類查詢商品圖片。然后經過模板渲染返回給瀏覽器。
具體思路以及圖片的上傳和下載如下:
l 用戶中心——訂單頁
(在訂單模塊進行開發)
7.2 商品模塊設計——goods
l 商品首頁 /index
Get請求:
判斷用戶是否登陸,若登陸了獲取用戶信息,獲取購物車中數目信息。獲取商品類型信息,獲取首頁商品輪播信息,獲取首頁商品類型輪播信息,獲取首頁活動輪播信息,通過模板進行渲染,返回給用戶。為提高網站性能和安全性
- 使用頁面靜態化方法
在管理員對首頁信息添加或修改之后,利用celery異步生成一個靜態頁面,只要頁面沒有數據更新,用戶直接返回這個靜態頁面,減少查詢數據庫的次數。使用nginx來調度訪問Django網站還是訪問nginx。
- 使用頁面數據緩存方法
在頁面信息被修改時清除緩存數據,使用redis存儲緩存數據,用戶訪問網站時,如果從緩存中沒有找到數據,則從數據庫中獲取並存入緩存,否則直接使用緩存。同樣減少了查詢數據庫的次數。
l 商品詳情頁 /goods/detail/(good_id)
Get請求:
判斷用戶是否登陸,若登陸了獲取用戶信息,獲取購物車中數目信息。獲取商品SKU信息,獲取SKU商品的同類型SPU的所有SKU商品信息,獲取商品類型信息,獲取同類型商品新品信息,獲取訂單商品信息。通過模板進行渲染,返回給用戶。
l 商品列表頁 /goods/list/(type_id)/(page)?sort=sort_method
Get請求:
判斷用戶是否登陸,若登陸了獲取用戶信息,獲取購物車中數目信息。獲取商品類型,獲取商品類型信息,獲取同類型商品信息,將同類型商品信息分頁(需要用到Paginator類,參見https://www.jianshu.com/p/332406309476),獲取當前頁面上商品。通過模板進行渲染,返回給用戶。
l 搜索功能的實現
商品模塊每個頁面都有一個搜索框,實現搜索功能:首先是把 django haystack 加入到 INSTALLED_APPS 選項里,再添加配置,
django haystack 規定。要相對某個 app 下的數據進行全文檢索,就要在該 app 下創建一個 search_indexes.py 文件,然后創建一個 XXIndex 類(XX 為含有被檢索數據的模型,如這里的 Goods SKU),並且繼承 SearchIndex 和 Indexable。
我們使用數據模板去建立搜索引擎索引的文件,接下來就是配置 URL,修改一下搜索表單,讓它提交數據到 django haystack 搜索視圖對應的 URL,使用 Whoosh 作為搜索引擎, haystack_search 視圖函數會將搜索結果傳遞給模板 search/search.html,因此創建這個模板文件,對搜索結果進行簡單渲染,
但在 django haystack 中為 Whoosh 指定的分詞器是英文分詞器,可能會使得搜索結果不理想,把這個分詞器替換成 jieba 中文分詞器,
最后一步就是建立索引文件了,運行命令 python3 manage.py rebuild_index 就可以建立索引文件了。
7.3 購物車模塊設計——cart
l 加入購物車功能 /cart/add
Post請求: 從商品詳情頁發來ajax post型請求,
# 請求方式:ajax post
# 傳遞參數:商品id sku_id ,商品數量 count
# 返回: 成功:JsonResponse({'res':5, 'message': '添加成功', 'total_count': total_count})
根據數據進行處理:往購物車里添加商品,購物車用redis存儲,
返回數據之后原頁面對應顯示信息。
l 顯示我的購物車頁面 /cart
Get請求:用戶未登錄不可訪問, 獲取用戶信息,從redis中獲取用戶的購物車中商品列表,給商品動態添加小計和數目屬性,組織參數返回給模板,模板渲染遍歷顯示,返回給用戶。
l 更新購物車功能 /cart/update
Post請求: 從我的購物車頁面發來ajax post型請求,
# 請求方式:ajax post
# 傳遞參數:商品id sku_id ,商品數量 count
# 返回: 成功:JsonResponse({'res':5, 'message': '更新成功', 'total_count': total_count})
根據數據進行處理:更新購物車里商品,購物車用redis存儲,
返回數據之后原頁面對應顯示信息。
l 刪除購物車中商品功能 /cart/delete/
Post請求: 從商品詳情頁發來ajax post型請求,
# 請求方式:ajax post
# 傳遞參數:商品id sku_id ,商品數量 count
# 返回: 成功:JsonResponse({'res':3, 'message': '刪除成功', 'total_count': total_count})
根據數據進行處理:往購物車里添加商品,購物車用redis存儲,
返回數據之后原頁面對應顯示信息。
l 前端說明
主要使用js,jquery 進行頁面更新。主要實現以下功能:
Detail.html
1 計算和設置商品總價格(在購物車頁面是小計)
2 增加商品數量
3 減少商品數量
4 手動輸入商品數量
5 添加到購物車 發起ajax請求 # 請求方式:ajax post # 傳遞參數:商品id sku_id ,商品數量 count, 實現購物車數量改變。
Cart.html
1 計算被選中的商品的數量和總價格
2 計算商品小計
3 更新購物車中的商品數量 發起ajax請求 # 請求方式:ajax post # 傳遞參數:商品id sku_id ,商品數量 count, 實現購物車中商品數量改變,成功與否返回相應信息。
4 商品的全選和全不選功能
5 單個商品的checkbox改變時,設置全選與否
6 購物車商品數量的增加 若3成功,更新頁面
7 購物車商品數量的減少 若3成功,更新頁面
8 手動輸入購物車商品數量 若3成功,更新頁面
9 刪除購物車中的記錄 發起ajax請求 # 請求方式:ajax post # 傳遞參數:商品id sku_id, 實現購物車中商品數量改變,成功與否返回相應信息並相應改變頁面。
7.4 訂單模塊設計——order
l 提交訂單頁面:顯示用戶准備購買的商品信息。
Post請求:從購物車頁面點擊去結算,發起post請求,提交的參數有:選中的商品的列表。查詢redis中商品的數量,再計算出商品的小計,計算出總數量和總價格,再查出來地址信息,一並顯示給用戶。
l 點擊提交訂單完成訂單的創建。
Post請求:用戶點擊提交訂單發起ajax post請求,提交參數有:地址id、支付方式、商品列表字符串。生成訂單信息表,查詢每種商品的庫存和購買數量,判斷是否購買成功,成功則向訂單商品表中添加數據,失敗則返回錯誤信息,並回滾數據庫事務,此時需要用到mysql的事物以及加鎖和隔離內容,加鎖方式有兩種,悲觀鎖和樂觀鎖,我提供了兩種,最終跳轉到相應頁面。
l 用戶中心訂單頁顯示用戶的訂單信息。
Get請求;查詢訂單信息,分頁顯示。
l 點擊支付完成訂單的支付
Post請求:用戶發起ajax post請求,提交訂單參數,網站生成對應支付方式的支付頁面地址。如果請求成功,get請求支付頁面,前往支付。另一方面,網站監聽支付結果(因現在沒有公網ip),如果支付成功則提示支付成功,跳轉到訂單頁面。
我只實現了支付寶支付方式:使用pip3 install alipay-sdk-python
l 點擊評價完成訂單的評價 /order/comment/(order_id)
Get請求:查詢訂單信息,返回提交評論的頁面。
Post請求:提交評論,跳轉到訂單頁。