$2015 武漢森果公司web後端開發實習日記----書寫是爲了更好的思考

  找暑期實習,3月份分別投了百度和騰訊的實習簡歷,都止步於筆試,總結的主要緣由有兩點:基礎知識不紮實,缺少項目經驗.後來到拉勾網等網站上尋找實習,看了不少家,都仍是處於觀望狀態.後來參加了武漢實習吧在大活舉辦的實習分享會,聽完後最大的收穫是獲取了更多的信心.再過了幾天偶然看到了年級羣郵裏發的一篇We信水果幫的實習招聘,加上發現是以前認識的學長髮的郵件,因而和學長了解了一下狀況,把簡歷發出去了.沒過兩天5月15日就收到了面試通知.面試以後,內心一陣緊張,畢竟是第一次經歷求職面試,不過還算順利,面試經過.不巧的是恰逢考試周,考試周考完兩門後就到公司開始了正式的實習. javascript

【5.27】css

  下午考完期中考試最後一門接口技術,晚上和陳明一塊兒到森果公司辦公室,作到快十點,主要是配置系統開發的環境。今天完成的主要內容:html

  一、 熟悉Github的用法:clone代碼到本地(須要命令行命令)。前端

  二、 clone森果網站的代碼到本地,並配置本地數據庫,跑通入口程序。在喬遷學長的幫助下,瞭解網站架構,把網站的功能和代碼進行對比。java

  三、 產生的困惑:因爲對tornado框架和sqlalchemy框架的不熟悉,致使對代碼的理解不是很好,後來回去跟廖思敏學長聊,學長建議先把這兩個框架官網上的Demo都跑通再說。此外還有對python的熟悉。node

【5.29】python

  這兩天天天都是早上9點半左右到公司,一直到晚上八九點.29號早上下雨了,整個上午天都是陰沉沉的,不過很涼快.水果幫網站在這兩天也新增了功能,有一個功能就是在微信裏實現支付寶支付,黑科技~贊一個~還有就在這幾天支付寶的光纖被挖掘機挖斷了,攜程的服務器被攻擊了,互聯網安全的問題凸顯出來了.對了今天李晨和范冰冰發微博公開戀情出現'咱們體'.mysql

  這兩天作的事情有以下幾點:jquery

  一、 繼續熟悉整個系統.linux

  二、 使用和了解worktile團隊協做工具.

  三、 試着實現商家後臺訂單管理中根據不一樣條件對訂單進行篩選和排序的功能.

  四、 初步完成了3中的代碼,等待調試.但在調試的過程當中遇到了沒法登陸本地網站服務器的問題,29號下午調試了一下午都沒有解決,主要排查了nginx的配置 ,hosts文件,數據庫數據等,反反覆覆試錯了不少次,到晚上尚未解決.最終發現是由於昨天學長給的數據庫並無包含以前在網站註冊的數據,所以登陸不上,這算是一個低級的錯誤.想到的解決方案是:從新註冊之後並綁定手機號,而後從喬遷學長那裏用新的數據庫進行本地測試.

  五、 初步熟悉postman(chrome瀏覽器)和httprequest(firefox瀏覽器)這兩個web開發工具的使用.

  六、 今天相關的資料和文檔記錄在:①快盤的Daily文檔;②worktile的Daily文檔;③firefox的Daily書籤裏.

【5.30】

  考試周完太累了,想休息一下,跟學長請假一天.主要是給妹子裝數據庫,教她數據庫.在教的過程當中本身也小小的複習了一下.

【5.31】

  繼續到公司上班,今天只有兩個學長在,其餘小夥伴都休息了.今天作的主要事情有:

  一、 調試系統網站的本地測試,依然沒有成功.

  二、 深刻練習了GitHub的使用,並測試提交代碼與版本控制的功能(主要參照了'廖雪峯的官網'上的GitHub教程進行練習,總結在這篇博文裏面:http://www.cnblogs.com/jiayongji /p/4542388.html

  三、 今天的文檔記錄在:worktile的Daily文檔.

【6.1 週一】

  今天解決了困擾兩天的問題,從新導入了學長給的線上版數據庫,成功解決了以前不能登陸/admin的問題. 但偶爾出現了退出店鋪後臺不能再次登陸的問題,解決方法是用登陸頁面上找回密碼的功能發手機驗證碼從新設置密碼,而後再到登陸頁面用手機號和新密碼登陸便可.所作的工做有:

  一、 進入系統進行訂單管理新增功能的功能測試.在反覆調試中掌握了先後端交互數據的形式.須要注意的有如下幾點:

    ①在不斷往本地系統中添加新數據後,儘可能要常常備份數據庫.最好本地和網盤上都備份一份.在終端中用這個命令備份數據庫:$ mysqldump -uroot            -p*** abc > abc.sql(導出數據庫abc到當前目錄下保存爲abc.sql文件,’***' 表示mysql的登陸密碼)

    ②pyton3 app.py –debug=1 #調試模式,每次修改代碼後不用重啓便可實時更新.

    ③測試後臺的單獨功能的時候直接在地址欄中添加和改變參數的值進行測試,不要在頁面進行點擊測試!不然會出錯!!

    ④屢次測試的時候由於URL參數中多了空格而出錯,空格很不起眼,但仍然會致使頁面打不開!!這點在後面的測試的時候必定要注意!!

  二、 在實現多表鏈接查詢的排序功能的時候,屢次嘗試失敗,到晚上仍沒有找到解決方案,主要是由於對SQLAlchemy框架的操做不熟練,須要惡補框架知識.

  三、 今天的記錄文檔在:①Worktile Daily文檔;②瀏覽器Daily書籤;③快盤今日備份

【6.2 週二】

  早上起來看新聞看到湖北客輪沉沒,船上有四百多人,並且多爲老年人,祈禱.

  今天所作的工做有:

  一、 初步完成了店鋪後臺訂單管理中的訂單排序與篩選的功能,之因此說初步,是由於後端功能完成了,尚未與前端進行整合,並且代碼的效率還能夠進一步優化,主要是在數據庫查詢方面的優化,要求接下來繼續深刻學習sqlalchemy的相關知識.

  二、 這周的新任務是:實現超級管理員後臺的商鋪管理功能,與店鋪後臺的代碼邏輯比較類似,可是必需要充分優化效率,以應對大數據量.

  三、 進一步熟悉了整個系統的代碼結構和數據庫數據結構,可是對於表的聯合查詢的效率優化方面還有不少事情可作.

  四、 今天的相關文檔記錄在:①Worktile的Daily Tips文檔中;②瀏覽器的Daily書籤中,文件備份在快盤的Backup daily中.

 【6.3 週三】

  今天下午和晚上所作的工做有:

  一、 熟悉超級管理員後臺的代碼邏輯,重點熟悉店鋪管理的代碼邏輯和數據邏輯.

  二、 試着修改原有代碼,進行小的功能測試.

  三、 實現了部分排序功能,但由於數據量大,數據庫查詢效率低下,急需尋找高效率的方法或算法進行優化.

    如今想到的思路有:

    ①經過sqlalchemy對數據庫的shop表編制索引,提升查詢效率.

    ②嘗試使用海量數據排序算法,對數據排序進行優化.

  四、 sqlalchemy的知識還很欠缺,急待增強,能夠看今天瀏覽器書籤中的幾篇博文進行增強.

  五、 店鋪後臺訂單管理訂單篩選排序功能的後端代碼已經完成,前端實現推遲.

  六、 今天的文檔記錄在:①Worktile的Daily Tips文檔中;②瀏覽器的Daily書籤中,文件備份在快盤的Backup daily中.

【6.5 週五】

  這兩天主要實現總後臺店鋪管理功能,到6.5晚上已經基本完成,留下了兩個難點問題尚未解決.這兩天的工做總結以下:

  一、 這兩天修改的數據庫字段有:增長shop表的shop.fans_count(粉絲數)和shop.shop_property(店鋪銷售額)兩個字段,sql腳本在快盤今日備份文件夾中(明天預計還要增長的字段是滿意度字段).
  二、 完成了後臺店鋪管理中的店鋪排序和篩選功能,功能測試都正確;完成了店鋪信息卡顯示數據的大部分處理(綜合滿意度是個複雜的點,尚未攻克;還有按店鋪號或店鋪名搜索的功能也沒有實現,這個的實現方法能夠參照店鋪後臺訂單管理中的訂單搜索功能的實現).
  三、 要學習前端知識,從前端到後端的整個開發流程仍是要親身經歷一遍的,並且如今前端缺人手,本身要試着實現一些簡單的功能.看W3CSCHOOL上的前端html+css+js教程,或者到CSDN上找些入門的系列教程看.

  四、 陳明的ubuntu升級到15.10之後,重啓後進入不了系統,到windows下發現系統所在盤的全部文件都不見了,懷疑是在更新的時候感染了病毒,只好重裝系統,費時費力.並且裝ubuntu的時候最好裝LTS穩定版的系統,最新版的系統通常不是很穩定.

    so,保持天天雲端文檔備份和文件備份的好習慣.

  五、 今天文檔保存在:woktile 項目中;文件保存在:快盤DailyBackup中.

  六、 今天要整理快盤一週來的Backup,騰出本地空間.

【6.6 週六】

  今天把總後臺店鋪管理的兩個難點問題解決了,主要作的工做及總結以下:

  一、 完成了總後臺店鋪綜合滿意度的計算問題,解決方案是參照/list頁面店鋪滿意度的計算方法.

  二、 完成了總後臺按照店鋪號或店鋪名稱搜索的功能,實現方法是在url增長search鍵,假定將search框中輸入的關鍵字經過search傳給後臺,後臺根據關鍵字對數據庫進行篩選,篩選完畢之後再將數據返回給前臺.主要代碼以下:

 1 if 'search' in self.args:  #若是url中有'search' 2             from sqlalchemy.sql import or_   #導入sqlalchemy的or_,用於下方的判斷店鋪號或者店鋪名是否等於搜索關鍵字
 3             search = self.args['search']    #獲取search的值
 4             q = self.session.query(models.Shop).filter(or_(models.Shop.shop_name.like("%{0}%".format(self.args["search"])),   #數據庫查詢,將查詢結果賦給q
 5                        models.Shop.shop_code.like("%{0}%".format(self.args["search"]))),\
 6                        models.Shop.shop_status == models.SHOP_STATUS.ACCEPTED,\    #要是申請成功的店鋪
 7                        models.Shop.shop_code !='not set',models.Shop.status !=0 ).all()       #店鋪號非空(!='not set')而且店鋪不是關閉中
 8             shops = q
 9 else:
10             q = self.session.query(models.Shop)   #不然將整個Shop表賦給shops
11             shops = q.order_by(models.Shop.id).all()

  三、 下午學習了html/js/css的初步知識,熟悉了一下總後臺前端的代碼邏輯,爲下一步編寫總後臺的前端代碼作準備.

  四、 學長推薦用谷歌瀏覽器進行前端開發,但安裝了谷歌瀏覽器,修改nginx配置文件後,但是仍然登陸不了總後臺,這是個疑難雜症,因此仍是繼續用火狐.

  五、 今天的文檔文件和筆記記錄備份在:wortile項目文件中和Daily項目中,快盤Daily備份,firefox Daily書籤.

【6.7 週日】

  高考第一天,湖北數學驚現文言文大題;晚上韻苑體育館青春琴緣音樂會.

  今天主要是學習前端相關知識和總後臺店鋪管理數據分析,主要作的工做以下:

  一、 學習javascript基本語法,H5基本語法(主要在W3SHOOL上學).

  二、 繼續研究前端代碼結構,要接着學習javascript/h5/css/jquery.

  三、 新任務:在完成總後臺店鋪管理前-後端之後,再接着實現總後臺餘額管理的前-後端功能(與陳明協做).

  四、 今天的文件、文檔備份在:worktile Daily,快盤Daily,firefox書籤Daily.

  五、 總後臺店鋪管理數據分析:
    *將整形的sort_order映射成False(0)或True(1)
    *CustomerShopFollow表和orders表的連接查詢,用於篩選新/老用戶
    *篩選order_type和選定order_type相同的訂單
    *根據sort_key和sort_order對orders進行排序
    *根據選定的支付方式對orders進行篩選'
    *若是選定的order_status=5(全部訂單)

    (1)店鋪狀態(status=Column(Integer,default = 1) (0:關閉 1:營業中 2:籌備中 3:休息中)
      #鍵值對:"shop_status:int"
      全部(shop_status=5,shop.shop_status in [0,1,2,3,4])
      未激活(shop_status=4,shop_code = "not set")
      籌備中(shop_status=2 ,shop.shop_status=2)
      營業中(shop_status=1,shop.shop_status=1)
      休息中(shop_status=3,shop.shop_status=3)
      已停業(shop_status=0,shop.shop_status=0)

    (2)認證狀態(shop_auth =Column(Integer,default =0)(0:未認證 1:我的認證 2:企業認證 3:我的認證轉企業認證 4:企業認證轉我的認證)
      鍵值對:"shop_auth:int"
      全部(shop_auth = 4,shop.shop_auth in [0,1,2,3,4])
      已認證(shop_auth = 3,shop.shop_auth in [1,2,3,4])
      我的認證(shop_auth = 2,shop.shop_auth in [1,4])
      企業認證(shop_auth = 1,shop.shop_auth in [2,3])
      未認證(shop_auth = 0,shop.shop_auth=0)

    (3)排序規則:
      鍵值對:
      "shop_sort_key:int"
      值:
        0:註冊時間
        1:評價數
        2:帳戶餘額
        3:粉絲數

        4:訂單數
        5:營業額
        6:客單價

      [註冊時間]:create_date_timestamp
      [評價數]:old_msg
      [帳戶餘額]:available_balance
      [粉絲數]:
      *原來:self.session.query(models.CustomerShopFollow).filter_by(shop_id=shop.id).count()
      *增長字段後:shop.fans_count

      [訂單數]:order_count
      營業額:
      *原來:self.session.query(func.sum(models.Order.totalPrice)).filter_by(shop_id=shop.id).scalar()
      *增長字段後:shop.shop_property

      [客單價]:營業額/訂單數
      增長字段:single_price

    (4)排序順序:
      鍵值對:"if_reverse:int"
      值:
        0:升序
        1:降序

      鍵值對默認值:
        1.shop_status:5(全部)
        2.shop_auth:5(全部)
        3.shop_sort_key:4(默認按訂單數排序,降序)
        4.if_reverse:1(默認降序排列)
    (5)shop信息卡data數組:
      *店鋪名(data["shop_name"] = shop.shop_name)(店鋪名有超連接)

      *店鋪管理員暱稱(data["admin_nickname"] = shop.admin.accountinfo.nickname)(暱稱有超連接)

      *店鋪地址(data["shop_address_detail"] = shop.shop_address_detail)

      *auth_type_array = ['未認證','我的認證','我的認證轉企業認證','企業認證轉我的認證']
      *認證狀態(data["auth_type"] = auth_type_array[shop.shop_auth])

      *認證信息(超連接)()

      *店鋪號(data["shop_code"] = shop.shop_code)

      *create_date_trans = self.session.query(func.from_unixtime(shop.create_date_timestamp)).scalar()
      *註冊時間(data["create_date"] = self.session.query(func.date_format(create_date_trans,'%Y-%m-%d')).scalar())

      *shop_status_array = ['關閉','營業中','籌備中','休息中']
      *店鋪狀態(data["shop_shop_status"] = shop_status_array[shop.status])

      *申請信息(超連接)
      *評價數(data["old_msg"] = shop.old_msg)

      *滿意度()

 1 shop_id = shop.id
 2 orders = self.session.query(models.Order).filter_by(shop_id = shop_id ,status =6).first()
 3 if orders:
 4     q = self.session.query(func.avg(models.Order.commodity_quality),\
 5 func.avg(models.Order.send_speed),func.avg(models.Order.shop_service)).filter_by(shop_id = shop_id).all()
 6 if q[0][0]:
 7     commodity_quality = int(q[0][0])
 8 if q[0][1]:
 9     send_speed = int(q[0][1])
10 if q[0][2]:
11     shop_service = int(q[0][2])
12 if commodity_quality and send_speed and shop_service:
13     satisfy = format((commodity_quality + send_speed +             shop_service)/300,'.0%')
14 else:
15     satisfy = format(1,'.0%')
16 data["satisfy"] = satisfy

      *爲了提升效率,在shop末尾新加入三種'滿意度'字段:  ##忽然感受加這寫沒有必要,店鋪滿意度在/handlers/customer.py中已經有實現,爲什麼不直接調用呢?或者直接用那種方法實現呢?新方法見上方.

1 commodity_quality = Column(Float,default = 0,nullable = False) #value in 0~100
2 send_speed = Column(Float,default = 0,nullable = False)  #value in 0~100
3 shop_service = Column(Float,default = 0,nullable = False)  #value in 0~100

      *並寫以下腳本更新數據庫:

 1 use senguocc;
 2 alter table shop add column commodity_quality float(11) not null default 0;
 3 alter table shop add column send_speed float(11) not null default 0;
 4 alter table shop add column shop_service float(11) not null default 0;
 5 
 6 update shop set commodity_quality = 
 7 (
 8 select avg(senguocc.order.commodity_quality)
 9 from senguocc.order
10 where shop.id = senguocc.order.shop_id
11 );
12 
13 update shop set send_speed = 
14 (
15 select avg(senguocc.send_speed)
16 from senguocc.order
17 where shop.id = senguocc.order.shop_id
18 );
19 
20 update shop set shop_service = 
21 (
22 select avg(shop_service)
23 from senguocc.order
24 where shop.id = senguocc.order.shop_id
25 );

      *並在顧客購物後的處理方法中加入更新代碼:
        goods_count=len(shop.fruits) + self.session.query(models.MGoods).join(models.Menu).filter(models.Menu.shop_id == shop.id).count()
      *商品件數(data["goods_count"] = goods_count)

      *粉絲數(data["fans_count"] = shop.fans_count)

      *訂單數(data["order_count"] = shop.order_count)

      *營業額(data["shop_property"] = shop.shop_property)

1 if shop.order_count == 0:
2     single_price = 0
3 else:
4     single_price = shop.shop_property/shop.order_count

      *客單價(data["single_price"] = single_price)

      *帳戶餘額(data["available_balance"] = shop.available_balance)

      order表中:

1 commodity_quality = Column(Integer) #取值:0-100  
2 send_speed = Column(Integer) #取值:0-100  
3 shop_service = Column(Integer) #取值:0-100 
1 select commodity_quality from order inner join shop on shop.id = order.shop_id where shop.shop_name like '吃在 東農%';

  六、 解決整形值作除法會變成0的方法:
    88/100:結果是0
    float(88)/100:結果是0.88
  七、 根據店鋪號或店鋪名搜索的功能:
    search=水果&shop_auth=4&shop_status=5&shop_sort_key=0&if_reverse=0&

  八、 今日數據:快盤.

【6.9 週二】

  高考結束,相繼出來替考、聽力故障等事件。

  感受這兩天的狀態有點手忙腳亂的感受,一是自從開始研究前端的知識以及和後端的交互,都是一頭霧水的,須要學習的東西太多,而又不怎麼能抓住重點;二是課程的各類任務和實驗,拖延症致使的疲於應對。今天git又出了點問題,明天要解決。

  看着學長和小夥伴們作的熱火朝天的,各類新功能都實現了,解決了一個又一個問題,心中難免失落。無論怎樣,這兩天作的事情總結以下:

  一、 修正總後臺店鋪管理後端代碼的bug和缺陷,研究與前端的交互。

  二、 完成前端店鋪信息卡的修改和相關連接的跳轉,可是跳轉到的頁面仍是並不符合要求,這是下一階段的工做。修改相關路由以與本地服務器相匹配(事後往git上推代碼的時候還要改回來)。

  三、 陳明初步完成的店鋪管理功能還有幾個bug,此外還有與post請求和局部刷新等技術相關的難題沒有解決。

  四、 firefox用的UA要爲MicroMessenger,才能測試森果的微信申請功能。

  五、 html文件中能夠調用py文件中的方法,舉例以下(事先要先繼承base.html):

1 <p>
2     <span class="tit1">序號:{{shop.id}}</span>
3     <span>申請時間:{{handler.code_to_text("create_date_timestamp", shop.create_date_timestamp)}}</span>
4 </p>

  六、 這兩天的文檔文件備份在:worktile Daily,快盤 Daily,Firefox書籤。   

 【6.10 週三】

  昨天晚上寫數據庫的實驗報告到很晚,今天一直都昏昏沉沉的。一早醒來看到森果昨天夜裏更新的系統出了一些問題,微信羣裏都是商家在反映各類bug,學長們都在忙碌着解決問題。

  今天作的工做有:

  一、 研究前端經過post請求和ajax與後端進行數據交互,解決局部刷新的問題。

  二、 總後臺店鋪管理代碼bug的排查,這要在post請求交互數據的代碼中處理。

  三、 感受對於js很不熟練,對於jquery框架也不是很熟悉,從前認爲的前端開發就是寫寫html和css的想法徹底是錯誤的,前端的重中之重是js。

  四、 學長又分配了新任務,實現總後臺的訂單統計功能,要用統計圖的形式統計展示出來,這個能夠參考店鋪後臺的訂單統計的前端和後端的實現方法。

  五、 這一階段要惡補一下js的知識(主要是敲w3school上的代碼)。如今有個感覺是後臺的簡單功能實現有不少現成的代碼能夠參考能夠模仿,可是前端的實現以及與後端的交互這一塊必須對原理有了透徹的理解後才能實現功能。

  六、 之後熬夜不能超過一點半,不然次日徹底是昏昏沉沉的狀態,作什麼都沒有效率。

  七、 要整理一下worktile的文檔了,如今開始顯得有些雜亂了。

  八、 今天的文檔文件備份在:worktile Daily,快盤Daily,firefox書籤。

 【6.15 週一】

  今天所作的工做有:

  一、 實現了總後臺的訂單統計功能的python/js/html開發,繪出統計圖表。發現echarts是個功能很強大的東西,特別在數據統計方面,功能很實用,很豐富,很酷炫。

  二、 修正了以前總後臺店鋪管理的幾個BUG:

    ①shop表營業額字段的自動更新處理

    解決方法: 

    分別在staff.py和admin.py的shop.order_count += 1語句後添加:

      totalprice_inc = order.totalPrice 
      shop.shop_property += totalprice_inc

    經測試,原bug成功解決

    ②總後臺店鋪申請頁面佈局有錯誤

    通過反覆測試發現是在有未處理的店鋪申請的時候纔會出現佈局錯亂,因而重點排查對店鋪申請進行處理的html代碼,發現了問題所在.

    解決方法: 
      apply-manage.html第86行左右{% end %}的位置錯誤,且多了兩個右div。

    ③其餘幾個小BUG。

  三、 這兩天天天實現新功能後就往git上推代碼,經歷過以前幾天使用git的磕磕絆絆,如今已經可以熟練使用git推代碼了,無非是三步曲:

    假設當前的本地工做分支爲jyj.

    ①$ git fetch origin 遠程分支名:tmp  (tmp爲本地臨時分支)  #把代碼從遠程分支上更新到本地的tmp分支上.

    ②$ git merge tmp  (將tmp與當前分支合併,若是有衝突,手動修改衝突)  #合併tmp分支到當前工做分支,並手動修改衝突.

    ③$ git push origin jyj:遠程分支名  #將合併後的本地工做分支推到遠程分支上,若是指定的遠程分支不存在,則新建立一個分支.

    實現的新功能已經在測試服務器上跑起來了。

  四、 如今所用的從前端到後端的技術總結起來主要是這些:python後端-js中間層-html前端-css樣式修飾.

  五、 python3和mysql的datetime數據類型好像不兼容,這個明天要和學長進一步討論.

  六、 今天的文檔和文件保存在:worktile Daily,快盤,書籤Daily,github.

【6.17 週三】

  近幾日主要任務:總後臺每日對帳功能。

  一、 增長總後臺頁面的回到頂部按鈕:
    *base.html
    *superadmin-global.css
    *global.js

  二、 每日對帳html

1 <!--count-balance.html-->
2 <!--add by jyj 2015-6-16-->
3 
4 <li class="admin nav_item {{check_active}}">
5 <a href="{{reverse_url('superCheckCash')}}">每日對帳</a>
6 </li>
7 
8 <!---->

  三、 遇到問題: Python 'result' cannot be converted to a MySQL type
    查詢數據庫返回的結果是一個元組,只需取第0個元素便可.

  四、 tornado的標籤(if-else,for)

 1 {% if his["type"] == 2 %}
 2 <span class="tit1 orange-txt">-{{his["balance_value"]}}元</span>
 3 {% else %}
 4 <span class="tit1 orange-txt">+{{his["balance_value"]}}元</span>
 5 {% end %}
 6 
 7 for:
 8 {% for i in range(10)%}
 9 do something
10 {% end %}

  五、 每日對帳
    新建及修改文件:
    (1).superAdmin/count-balance.html
    (2).urls.py
    (3).superadmin.py: class CheckCash
    (4).superAdmin/balance-check.html
    (5).balance-check.js

  六、 加功能流程:
    ①先肯定在哪一個模板網頁上加功能--->②在該網頁上加上須要的html元素--->③在該網頁的頂部設置該元素的激活狀態變量,並設定激活條件,以及該元素的跳轉href名稱,這樣寫:href={{reverse_url
('superCheckCash')}}--->④在urls.py中添加該名稱對應的路由以及superadmin.py中的新增長類的名稱--->⑤在superadmin.py中增長新的類,實現後臺功能.先從簡單開始,只寫get方法,return渲染到新頁面.以後再豐
富功能--->⑥添加名字爲第⑤步中的渲染的網頁名稱的新網頁,引用須要的基本框架,在其中添加簡單的字符,以及在下方添加引用其對應的js文件--->⑦新建第⑥步中須要的js空文件--->⑧運行系統,看新增長的連接和
頁面可否正常加載.若是正常加載,則進一步豐富系統功能.

<div class="col-sm-12 col-md-12"></div>

  七、 css垂直居中:.align-center{padding:1px;}

    html空格:&nbsp;
    html換行:<br>

  八、 html中js的src要放在繼承的模板中才能生效.
    或者導入src的{%block%}塊名稱要與模板相同才能生效.

  九、 hide()和empty()方法均能讓一個控件隱藏.

  十、 點擊一個按鈕:
      1.讓一個控件或div隱藏或消失.
      2.往一個div中新增內容.
      3.獲取輸入框中的輸入內容.
      4.引發一個post方法.

1 $("#wx").text("lalala")
2 var wx = $("#wx-income").val()
3 wx = wx.toFixed(2);保留兩位小數

  十一、 js中加號被當成了鏈接符,若是要當作運算符,則先轉換爲整形或浮點型:
      parseFloat("123")=123

  十二、 models.py中相關的類:
      class ApplyCashHistory 提現
      class BalanceHistory 經過record間接獲取微信支付和阿里支付的錢數\

【6.18 週四】

  一、 postjson方法這樣用:
    (1)在js中:

 1 function showCheckInfo(page){
 2   var url = "";
 3   var data = 1;
 4   var args={
 5     data:data
 6   };
 7   $.postJson(url,args,function(res){
 8     if(res.success){
 9       alert(res.output_data);
10     }
11   });
12 }

    (2)在後臺superadmin中:

1 @tornado.web.authenticated
2 @SuperBaseHandler.check_arguments('data:int')
3 def post(self):
4 data = self.args["data"]
5 output_data = data + 333
6 return self.send_success(output_data=output_data)

    運行後會彈出一個提示框,顯示334.

    固然也能夠把data封裝成一個複雜類型的數據包:
    (1)js:

 1 function showCheckInfo(page){
 2   var url = "";
 3   var data={};
 4   data["a"] = 1;
 5   data["b"] = 2;
 6 
 7   var args={
 8     data:data
 9   };
10   $.postJson(url,args,function(res){
11     if(res.success){
12       console.log(res.output_data["a"],res.output_data["b"]);
13     }
14   });
15 }

    (2)後臺:

1 @tornado.web.authenticated
2 @SuperBaseHandler.check_arguments('data') #這一行必需要寫
3 def post(self):
4 data = self.args["data"]
5 output_data = data 
6 output_data["a"] = 555
7 output_data["b"] = 666
8 return self.send_success(output_data=output_data)

    在控制檯輸出:555 666

  三、 mysql獲取當前日期函數:now() 返回年月日時分秒

  四、 對於日期的一個處理:

1 now = datetime.datetime.now() - datetime.timedelta(1)
2 start_date = datetime.datetime(now.year, now.month, now.day, 0)
3 end_date = datetime.datetime(now.year, now.month, now.day, 23)
4 q = q.filter(models.Order.create_date >= start_date,\
5 models.Order.create_date <= end_date)

  五、 mysql的有些函數sqlalchemy並不能用.

  六、 收入總額要加入餘額消費的數據.
  七、 原本在對帳的時候,是能夠在js中根據加載完成後從後臺get到的數據的控件的id獲得而後進行比較的,不須要用post.可是考慮到數據精度,仍是在js中向後臺發post請求進行對帳.

  八、 js經過post向後臺傳遞的鍵值對的值都是str型的,若是須要比較大小等操做須要進行參數轉化.但後臺經過post向js返回的數據類型仍是原本的數據類型.

  九、 python中format的結果是str型(千萬要注意!),而round方法的結果纔是字符型,但round方法只能用於浮點數.
    如:a = round(3.445,2),則a = 3.45,type(a)爲float

  十、 考慮天天的對帳信息都要記錄下來,因此在數據庫新創建一個對帳表check_profit:

 1 create table check_profit(
 2 id int(5) primary key not null auto_increment,
 3 create_time datetime not null, 
 4 is_checked int(1) default 0,
 5 wx_record float(11) default 0,
 6 wx_count_record int(11) default 0,
 7 alipay_record float(11) default 0,
 8 alipay_count_record int(11) default 0,
 9 widt_record float(11) default 0,
10 widt_count_record int(11) default 0,
11 total_record float(11) default 0,
12 total_count_record int(11) default 0,
13 
14 wx float(11) default 0,
15 wx_count int(11) default 0,
16 alipay float(11) default 0,
17 alipay_count int(11) default 0,
18 widt float(11) default 0,
19 widt_count int(11) default 0,
20 total float(11) default 0,
21 total_count int(11) default 0
22 );

  十一、 sqlalchemy向數據庫中加數據示例:

1 balance_history = models.BalanceHistory(balance_record = '提現:管理員 '+name,balance_type =\
2 2,balance_value = apply_cash.value ,customer_id = apply_cash.shop.admin.accountinfo.id,name = \
3 name,shop_id = apply_cash.shop_id,shop_totalPrice = shop.shop_balance,superAdmin_id = \
4 self.current_user.id,available_balance = shop.available_balance)
5 self.session.add(balance_history)
6 self.session.commit()

  十二、 數據庫查詢時offset和limit的用法:

1 balance_history = self.session.query(models.BalanceHistory).filter(models.BalanceHistory.shop_id == shop_id,models.BalanceHistory.balance_type.in_([0,2,3])).order_by(desc 
2 (models.BalanceHistory.create_time)).offset(page*page_size).limit(page_size).all()

    注意:offset和limit要用在filter,order_by等的後面.offset表示先取偏移量,而後limit表示從偏移量位置開始取多少個.經常使用於分頁.並且偏移量是從0開始的.

  1三、 python和js中的/不是整除,而是帶小數的除法.

  1四、 天天對帳單的惟一性問題

【6.20 週六】

  一、 data={}要放在循環裏,不然會有詭異的錯誤
  二、 sqlalchemy delete操做用法:

1 self.session.query(models.CheckProfit).filter(models.CheckProfit.create_time == end_date,models.CheckProfit.is_checked==0).delete()

  三、 js中attr
  四、 分頁:兩種分頁方法的困惑.(頁面加載時候就發post請求,在js中寫渲染頁面的代碼的方案比較可行,簡潔);js模板引擎.
  五、 table標籤
  六、 js有時候有語法錯但不提示,會致使莫名其妙的錯誤.
  七、 html中if-else等的用法;塊的用法(tornado).
  八、 js中slice(m,n)函數至關於python中的切片操做.

  九、 js強制類型轉化:parseInt(),parseFloat()
  十、 js post分頁技術總結:
      (1)第1步:在html中建空表並用class(或id)標記,建上一頁下一頁按鈕並用class或id標識:

 1 <div class="pull-left">
 2 <table class="tb-account">
 3 
 4 </table>
 5 </div>
 6 <nav>
 7 <ul class="pager mlf300">
 8 <li><a href="javascript:;" id="PrePage">&larr; 上一頁</a></li>
 9 <li class="PageNow green-txt"></li>
10 <li><a href="javascript:;" id="NextPage">下一頁&rarr;</a></li>
11 </ul>
12 </nav>

      (2)第2步:在js中頁面加載裏面就引入渲染表格的方法showHistory(page),該方法須要向後臺發post請求以獲得返回數據,並且須要一個page參數:

 1 var page_sum = 0;
 2 var page_size = 20;
 3 var page = 1;
 4 $(document).ready(function(){
 5 getPageSum();
 6 showHistory(1);
 7 })
 8 showHistory(page)方法示例以下,其中用到了js模板引擎的技術:(一個小問題:在模板引擎中的html語句中怎樣使用if-else 9 function showHistory(page){
10 var url='';
11 var args={page:page};
12 $.postJson(url,args,function(res){ //post方法根據page參數獲取要顯示的數據
13 if(res.success){
14 var page_sum_now = parseInt(page_sum) ;
15 if(page_sum_now < page_sum){
16 page_sum_now = page_sum_now + 1;
17 }
18 $(".PageNow").text('-'+page+'/'+page_sum_now+'-');
19 var history = res.history;
20 $('.tb-account').empty(); //千萬要注意每次刷新新的一頁以前都要先清空以前的表格,不然顯示的內容會累加,達不到分頁的效果
21 for(i = 0;i<history.length;i++){ //獲取的數據history爲一個列表,該列表的元素爲字典
22 his = history[i];
23 
24 var item= '<tr>' //待會兒要向html的表格中添加的項,其中的數據在後面須要渲染。width屬性能夠控制每一列顯示的每一個元素的寬度所佔的百分比
25 +'<td class="pl10" width="20%">店鋪:<a href="/{{shop_code}}" title="點擊查看該店鋪餘額詳情" target="_blank" class=" text-blue">{{shop_name}} 
26 </a></td>'
27 +'<td width="17%">{{record}}{{name}}</td>'
28 +'<td width="21%">{{order_num_txt}}<a href="/super/orderManage/" target="_blank" class="text-blue">{{order_num}}</a></td>'
29 +'<td class="text-gray" width="15%">{{time}}</td>'
30 +'<td class="txt-ar" width="12%"><span class="orange-txt">{{balance_value}}</span>元</td>'
31 +'<td class="txt-ar pr10" width="15%"><span class="green-txt">{{balance}}</span>元</td>'
32 '</tr>'
33 var render=template.compile(item); //生成渲染器
34 
35 //給變量賦值
36 var shop_code = his["shop_code"];
37 var shop_name= his["shop_name"];
38 if(shop_name.length >=8){
39 shop_name = shop_name.slice(0,7) + '...';
40 }
41 var type = his["type"];
42 var record = his["record"];
43 var name = his["name"]
44 if(name.length >=6){
45 name =name.slice(0,5)+'...';
46 }
47 var order_num_txt = his["order_num_txt"];
48 var order_num = his["order_num"];
49 var time=his["time"];
50 var balance_value = his["balance_value"];
51 if(type == 2){
52 balance_value = '-' + balance_value;
53 }
54 else{
55 balance_value = '+' + balance_value;
56 }
57 var balance = his["balance"];
58 
59 //渲染表格項
60 var list_item =render({
61 shop_code:shop_code,
62 shop_name:shop_name,
63 type:type,    
64 record:record,
65 name:name,
66 order_num_txt:order_num_txt,
67 order_num:order_num,
68 time:time,
69 balance_value:balance_value,
70 balance:balance
71 });
72 
73 //向表格中添加渲染後的項:
74 $('.tb-account').append(list_item);
75 }
76 }
77 else{
78 alert(res.error_text);
79 }
80 },
81 function(){alert('網絡好像不給力呢~ ( >O< ) ~');}
82 );
83 }

      (3)第3步:添加上一頁和下一頁按鈕的click事件:

 1 $(document).ready(function(){
 2 getPageSum();
 3 showHistory(1);
 4 }).on("click","#PrePage",function(){
 5 if(page == 1){
 6 alert("當前已是第一頁了~");
 7 return false;
 8 }
 9 else{
10 page--;
11 showHistory(page);
12 }
13 }).on("click","#NextPage",function(){
14 
15 if(page >= page_sum){
16 alert("當前已是最後一頁了~");
17 return false;
18 }else{
19 page++;
20 showHistory(page);
21 }
22 });

  十一、 從數據庫中刪除數據示例:

1 self.session.query(models.CheckProfit).filter(models.CheckProfit.create_time == end_date,models.CheckProfit.is_checked==0).delete()

  十二、 其實若是對帳成功,那麼CheckProfit表中的記錄值和實際值確定是同樣的;若是尚未對帳,那麼CheckProfit表中只會有記錄值。因此向前臺返回數據的時候沒有必要把全部數據都返回,而只須要把記錄的數據返回
便可。
  1三、 sublime中html仍是識別不了註釋。

  1四、 常常將js和python的變量定義方法搞混...python的普通變量定義是能夠直接拿來就用的,而js是要寫var的,切記!!!js不寫var的變量是全局變量。

  1五、 今日數據:快盤,github.

【6.21 週日】

  一、 mysql中日期格式轉換函數:
    DATE_FORMAT(date,format)
    根據format字符串格式化date值。下列修飾符能夠被用在format字符串中: %M 月名字(January……December)

 1 %W 星期名字(Sunday……Saturday)
 2 %D 有英語前綴的月份的日期(1st, 2nd, 3rd, 等等。)
 3 %Y 年, 數字, 4 4 %y 年, 數字, 2 5 %a 縮寫的星期名字(Sun……Sat)
 6 %d 月份中的天數, 數字(00……31)
 7 %e 月份中的天數, 數字(0……31)
 8 %m 月, 數字(01……12)
 9 %c 月, 數字(1……12)
10 %b 縮寫的月份名字(Jan……Dec)
11 %j 一年中的天數(001……366)
12 %H 小時(00……23)
13 %k 小時(0……23)
14 %h 小時(01……12)
15 %I 小時(01……12)
16 %l 小時(1……12)
17 %i 分鐘, 數字(00……59)
18 %r 時間,12 小時(hh:mm:ss [AP]M)
19 %T 時間,24 小時(hh:mm:ss)
20 %S 秒(00……59)
21 %s 秒(00……59)
22 %p AM或PM
23 %w 一個星期中的天數(0=Sunday ……6=Saturday )
24 %U 星期(0……52), 這裏星期天是星期的第一天
25 %u 星期(0……52), 這裏星期一是星期的第一天
26 %% 一個文字「%」。

  二、 datetime.timedelta(1)的結果爲:1 day,0:00:00

  三、 balance_history表是無論天天有沒有記錄都會自動建立嗎?
  四、 檢查昨天的對帳單是否建立,若是沒有建立,說明balance_history的昨天的在線支付、用戶餘額充值的記錄爲空,說明昨天的對帳單的記錄值爲0,這仍是要建立check_profit表的昨天的數據的,只不過
收入數據和提現數據每一項都爲0.
  五、 artTemplate 原生語法是否支持if...else:
    這樣的寫法:
      <%if(…){%> html <%}else{%> html <%}%>
    或者這種寫法:

      {if ...}html{else}html{/if}
    但是好像都用不了?
    正確寫法:
      {{if ...}}...{{else}}..{{/if}}
  六、 模板引擎arttemplate
  七、解決artTemplate中不能使用if-else的問題:
    這樣解決:
      (1)先提早判斷條件type的取值:

1 if(type == 2){
2 var item2 = '<td width="17%">{{record}}{{name}}</td>';
3 }
4 else{
5 var item2 = '<td width="17%">{{record}}<a href="/super/user" title="點擊查看該用戶詳情" target="_blank" class=" text-blue">{{name}}</a></td>';
6 }

      (2)而後將其加入item中:

1 var item= '<tr>'
2 +'<td class="pl10" width="20%">店鋪:<a href="/{{shop_code}}" title="點擊查看該店鋪商品首頁" target="_blank" class=" text-blue">{{shop_name}}</a></td>'
3 +item2
4 +...

      (3)再生成模板渲染引擎:

1 var render=template.compile(item);

      (4)再按照原來的步驟作便可。

  八、 css遮罩層

  九、 js中動態生成的button用jquery怎樣添加點擊響應事件?
    (jquery獲取不到動態建立的元素id)
    在js中動態生成了一個button,並且它的name是從數據庫中得到是數據,也就是說我不知道當前點擊的的button的id是什麼,並且生成button是循環作的,一次會生成多個。我想用jquery獲取他的name。 用js寫的話可
以onclick=function(this),想問用jquery怎麼作?

  十、 讓css遮罩層不隨滾動條的滾動而消失的方法:
      將遮罩層的position樣式改成fixed便可。

  十一、 jQuery中在循環中綁定事件容易出現的問題.
      解決方法:

1 ...(artTemplate模板引擎代碼)
2 $(".tb-history").append(list_item);
3 $("#btn-check-"+i).click(function(i){
4 return function(){
5 alert(i+"xxxxxxxxxxxxx");
6 }; //若是在這個btn點擊之後還要監聽其餘按鈕的click事件,則要把其餘按鈕放在這個click事件中,並且也要用這種形式的函數。
7 }(i));

【6.22 週一】

  一、 jquery循環綁定只能獲取到最後一個元素的值的問題;js閉包問題;代理。
  二、 獲取第i個子元素。
  三、 each方法遍歷。
  四、 動態綁定的button的click事件中再添加其餘button的click事件,但爲何連續發了好幾個post請求??

  五、 重命名文件的命令:
    mv a.txt b.txt #把文件a.txt重命名爲b.txt

  六、 總後臺店鋪餘額詳情和每日對帳功能完成!
    小結:
    1.一開始的時候數據邏輯和功能邏輯沒有理清楚,走了一些彎路。
    2.分頁的時候原本打算用url傳值的方法,可是由於每一個item要處理的數據較多,並且裏面的button有點擊事件,這樣的方式實現起來比較複雜。後來參考了一下系統的有一部分代碼,以爲從頁面加載開始就用post方法
+artTemplate模板引擎渲染頁面的方式會比較好,但會影響一些效率。post方法在剛剛開始作的時候比較順利,可是後來遇到了循環動態綁定的問題,按照常規的方法沒法獲取到動態生成的元素的id,着實費了很大一番
功夫才解決。在這個過程當中遇到了js的代理、閉包等高階的技術,到如今仍是雲裏霧裏的,須要好好學習一下,之後還要用到。
    3.由於要實現點擊按鈕彈出一個輸入多個數據窗口的功能,一開始想的是js裏有沒有現成的這樣的控件來用,後來發現還真的沒有,在周兵學長的提示下,去網上查了js+css遮罩層的技術,發現正符合要求,因而仿照
demo實現了這個功能。
    4.經過這個功能的實現,對新功能實現的從前臺到後臺的整個流程已經很熟悉了,對js/css/html三者的瞭解更多了,能在新功能中熟練操做它們。css的調試好費神。。
    5.html中table元素在顯示列表的時候很規整,看起來很舒服,最好配合artTemplate引擎渲染。
    6.對js的測試技術感覺很深:到處用alert...alert是個好東西,仍是不會用firebug的調試功能。

  七、 新任務:總後臺-用戶。用戶選項裏,增長用戶ID 、出生日期 的顯示。 增長搜索:id、用戶暱稱

  八、 相關文件:superadmin.py,superadmin-user.js,user.html,user-item.html,superadmin-user.css,models.py
  九、 python將時間戳轉化爲日期:

1 b_time_stamp = 776361600
2 print(type(b_time_stamp))
3 dateArray = datetime.datetime.utcfromtimestamp(b_time_stamp)
4 birthday = dateArray.strftime("%Y年%m月%d日")
5 print(birthday)

    輸出:1994年08月08日

  十、 python中list方法

  十一、 點擊連接變成了綠色而並列的其餘連接變回原來的顏色,這是怎麼實現的?(當點擊連接後連接變色,切換別的連接,又恢復原來樣子)
    解決方案:
    1.首先在html中有相似這樣的代碼,表示3個連接(注意其中‘{{}}’中的變量):

 1 <li class="all nav_item {{detail_active}}">
 2 <a href="{{reverse_url('superBalance')}}">餘額詳情</a>
 3 </li>
 4 <li class="admin nav_item {{cash_active}}">
 5 <a href="{{reverse_url('superApplyCash')}}">提現申請</a>
 6 </li>
 7 <!-- add by jyj 2015-6-17 -->
 8 <li class="admin nav_item {{check_active}}">
 9 <a href="{{reverse_url('superCheckCash')}}">每日對帳</a>
10 </li>

    2.在html頂部寫相似於這樣的語句:

 1 {% set page = context.get("page", "detail")%}
 2 {% set detail_active = ""%}
 3 {% set cash_active = ""%}
 4 {% set check_active = ""%}
 5 
 6 {% if page == "detail"%}
 7 {% set detail_active = "active"%}
 8 {% elif page == "cash"%}
 9 {% set cash_active = "active"%}
10 {% else %}
11 {% set check_active = "active"%}
12 {% end %}

    3.在後臺實現該功能的類中,在get方法最後render的時候要有context屬性,相似於這樣:

1 def get(self):
2 ...
3     return self.render("superAdmin/balance-check.html",output_data=output_data,context=dict(page='check'))

    4.在某一個相關的全局css中要有li標籤的active屬性的顏色值,或者a標籤的visited屬性的顏色值。

【6.23 週二】

  一、 bug:總後臺用戶管理中點擊‘關注的店鋪’後跳轉到一個錯誤頁面:已解決!a標籤的href屬性錯誤問題。
  二、 bug:總後臺店鋪管理全部店鋪中,點擊搜索後搜索結果中的店鋪名稱消失了:已解決!在js中刷新搜索結果的頁面時沒有添加店鋪名的a標籤值。
  三、 js中即時搜索的實現:

1 var input = $("#inputinfo");  //inputinfo表示搜索輸入框的id
2 input.on('keyup',function(){
3         page=0;
4         getSearchContent('search',$("#inputinfo").val(),page);
5 });  //getSearchContent是向後臺發出post請求並根據返回的數據渲染頁面的函數。

  四、 sqlalchemy中將整形轉化爲字符串的函數:
    func.concat(models.Accountinfo.id,'')
  五、 sqlalchemy中like的用法:
    q = q.filter(or_(models.Accountinfo.nickname.like("%{0}%".format(inputinfo)),(func.concat(models.Accountinfo.id,'')).like("%{0}%".format(inputinfo))))
  六、 完成總後臺用戶管理搜索和完善信息卡功能!

  七、 數據備份:快盤.

【6.24 週三】

  一、 bug:在測試服務器上看,總後臺店鋪餘額詳情頁面上方的"提現中"數據有問題,顯示的是當前系統最新的提現數據,而不是該店鋪的正在提現的數據.

  二、 優化:總後臺訂單統計的送達時間統計的"昨日數據"的查詢效率很低.

  三、 bug:超級管理員用戶管理js報錯:TypeError: fshop[j] is undefined:已解決!
    緣由:在壓縮用戶名的時候,沒判斷用戶關注的店鋪是否爲空,致使出現關注店鋪列表不存在的狀況.

  四、 mysql把時間戳轉化爲日期:
      mysql>SELECT FROM_UNIXTIME( 1249488000, '%Y%m%d' )  
      ->20071120
  五、 問題:python用以下方法把時間戳轉化爲日期結果少一天:

1 b_time_stamp = 541008000
2 dateArray = datetime.datetime.utcfromtimestamp(b_time_stamp)
3 birthday = dateArray.strftime("%Y-%m-%d")

      輸出爲:1987-2-22
      而實際上應爲:1987-2-23
      (好像是python的一個bug...)
    解決方法:用mysql的時間戳轉換函數.
  六、 bug:總後臺用戶管理搜索之後再刷新頁面再點下一頁會沒有東西,必須把搜索框中的內容刪除掉纔會正常:搜索框緩存清理問題.
    解決方法:在js的getContent方法開始加上一句代碼:$("inputinfo").val('');  清空輸入框緩衝區,便可解決問題.

  七、 數據,代碼和文檔備份:快盤.

【6.29 週一】

  又是一個週一,發現已經兩週沒有更新博客了。以前一週多一直在加班和複習期末考試,再加上自身的拖延症,致使一擱置就是兩週。不過技術上,以前天天的工做日誌文檔記錄的都很詳細,遇到、解決的問題和Bug也有記錄;生活上,複習複習複習+實驗報告實驗報告實驗報告,呃...固然天天和她在一塊兒複習仍是很棒很棒的。

  今天是期末考試的第一天,複習之餘來點小總結放鬆一下。

  第一件事,前天下午去光谷創業咖啡參加的segmentfault組織的技術沙龍,真心不錯。第一次參加這種外面的技術沙龍,各個領域的大神不少,除了抽了兩次kindle都沒有抽到和熱浪滾滾的天氣之外,其餘都仍是很愉快的,特別是森哥專門爲沙龍提供的水果很好吃,很解渴。

  nodejs,x11,光谷社區,持續集成,單元測試,docker,自動化測試,GUI,開源字體github.com/ecomfe/fontmin...這些是關鍵詞。一個小小的字體能玩出太多的花樣,也能夠搞各類優化;上古GUI——Alt+Tab的底層原來有那麼多的細節要考慮,自覺得熟練使用GTK原來還差的遠着呢。

  深度科技的deepin操做系統印象深入,感受很適合程序員,愛折騰的程序員;圓桌會議的支持人賀鈞大神原來是喬遷學長的哥們,世界略小。最後,光谷社區是個好地方。

  第二件事,這兩天寫實驗報告真是寫苦了,各類排版,不得已把當時組原課設的實驗報告拿來,用其中已經設置好的各類樣式當模板了,當時老譚真是下了一番功夫,不得不說組原課設的模板真的很贊。完成實驗報告之後因而決定狠下心來把各類報告、論文寫做的基本和高端的排版技巧學一學,之後(至少一年以內)處處用獲得,隨後會在另外一篇博文中常常更新天天get到的新技能。

  第三件事,沒有更新的兩週的博客內容會在臨近這週末的幾天裏總結出來,主要是各類技術問題。

【7.4 週六】

  考完試後的第一天,感受一會兒輕鬆了很多.下午到公司,陳明由於家裏有點事情要請一段時間的假,我本身在公司寫了一下午和一個晚上代碼.

  今天完成的任務和遇到的問題總結以下:

  一、 實現新功能:總後臺餘額詳情表格中新增長一列,把全部店鋪餘額不爲零的店鋪名和店鋪餘額列出來,以及最近一次餘額變更的時間.這個問題比較簡單,只需從balancehistory表中查詢,按照店鋪id分組,查出每一組中create_time最大的項的店鋪ID和店鋪餘額便可.但是在這個過程當中遇到了問題,關於sqlalchemy的子查詢和分組查詢的問題,查出的數據一直不對,費了一番周折.最後想到了一個間接的方法,就是先把全部店鋪的全部餘額變更記錄從balancehistory表中查詢出來,並按create_time降序排序;而後用python對這個列表進行遍歷,先設置一個空的記錄表exist_id_list,每次循環先判斷當前記錄的shop_id是否在記錄表中,若是不在,就把這條記錄對應的shop_id加入記錄表中,而後把shop_id,shop_totalprice,create_time三項數據插入一個字典中,而後把字典加入到一個列表中;若是在,就pass,進行下一輪循環.循環完畢後,獲得的列表就是前端所須要的數據,再傳給前端便可.

    但是作完之後檢查發現數據仍是有些問題,通過測試發現經過上述方法計算出的系統總餘額與經過shop.shop_balance累加出來的系統總餘額不一致,前者比後者要多,可是覈查每一個店鋪的賬又都是一致的.這個問題仍是要等週一的時候跟學長討論一下.

  二、 今天遇到另一個比較糾結的問題是,由於瀏覽器的cookie過時了,加上沒有權限,以前能登進去的總後臺今天忽然登不進去了.安裝了火狐瀏覽器的Advanced Cookie Manager插件查看cookie後才發現原來的cookie到6.26號已通過期了,而那些天正在期末考試沒有發現.又折騰了好長時間才解決問題,解決的方法以下:

    ①安裝火狐Advanced Cookie Manager插件。
    ②用學長的手機掃描i.senguo.cc的super登陸頁面二維碼,此時登陸cookie就已經存儲在了cookie文件裏。
    ③在剛剛安裝的插件中找到zone.senguo.cc,刪除它下面的全部cookie.再次登陸zone.senguo.cc:8887/super,便可登陸成功!    

  三、 今天還遇到這個類型問題:從表中用分組查詢的方法查詢年齡最大的人的姓名,正確的應該是這樣:
    select name from infotable where birthday = (select min(birthday) from infotable);
    而不是:select name,min(birthday) from infotable;

    例:有people表:

      +----+------+-------+
      | id | name | grade |
      +----+------+-------+
      |  1 | aa   |    90      |
      |  2 | bb   |    95      |
      |  3 | cc   |    87      |
      +----+------+-------+

    從中查詢grade最低的人的姓名,若是這樣查:select name,min(grade) from people;  結果是:aa  87,顯然不對;
    正確的應該是這樣查:select name from people where grade=(select min(grade) from people);  結果是:cc,結果正確.

  四、 以前寫的每日對帳功能存在一個bug:線上系統缺了一週的數據,並且數據更新邏輯有問題.

  五、 js保留兩位小數:number = number.toFixed(2)
    python保留兩位小數:number = round(number,2)

  六、 今天發現senguo的git上有artTemplate的資料,大喜,要好好學習一下.

  七、 數據,代碼和文檔備份:快盤.

【7.5 週日】

   今天同事們都放假,只有我一我的坐在那裏寫代碼.由於晚上要趕一篇論文,因此下午四五點時候就回去了.完成的主要工做有:

  一、 修復昨天的bug:經過shop.shop_balance算出的系統總餘額的帳和經過balancehistory算出的賬有出入.
    問題所在:後者的查詢邏輯有問題,數據庫篩選的時候漏掉了一個等於0的條件.
  二、 修復了以前的一個bug:在線上服務器上看,總後臺店鋪餘額詳情頁面上方的"提現中"數據有問題,顯示的是當前系統最新的提現中的金額,而不是這家店鋪的提現中金額.
    緣由:superadmin.py的ShopBalanceDetail類的get方法中,cash_applying = self.session.query(models.ApplyCashHistory.value).filter(models.           ApplyCashHistory.has_done == 0,models.ApplyCashHistory.shop_id == shop_id).first()中的models.ApplyCashHistory.shop_id == shop_id條件沒寫,加上即     可.
  三、 今天要完成任務:添加如下模塊:總後臺-店鋪-店鋪評論
    ①那種選中後下面有一條綠線的效果是怎麼作的.
      第一步:html中有這樣的代碼:

1 <ul class="tab-lst group">
2     <li class="active all-list">全部帳單</li>
3     <li class="cash-list">提現記錄</li>
4     <li class="charge-list">用戶充值</li>
5     <li class="online-list">在線支付</li>
6     <li class="ballance-list">餘額列表</li>
7 </ul>        

      第二步:對應的css中有:

1 .tab-lst{border-bottom: 2px solid #f6f6f6;-webkit-box-sizing: border-box;height:28px;}
2 .tab-lst>li{font-size: 14px;color: #666;line-height: 28px;float:left;height:28px;width:70px; margin-right: 20px;cursor: pointer;text-align: center;}
3 .tab-lst .active{border-bottom: 2px solid #52b43f;color: #52b43f;}

      第三步:js中爲ul的li添加click事件:       

1 .on("click",".tab-lst li",function(){
2     var index = $(this).index();
3     $(".tab-lst li").removeClass("active").eq(index).addClass("active");
4 });

    ②讓ul中的li橫向排列:只需給每一個li添加'float:left'屬性:.head-choose>li{float: left;}
    ③原來的店鋪評論頁面佈局有點錯亂.<---ok
    ④仿照admin後臺的條件選擇按鈕實現條件選擇按鈕.<---not ok
        太複雜了,仍是用總後臺店鋪管理陳明寫的那個選擇按鈕.
  四、 複製多個文件和文件夾夾到主文件夾下:sudo cp filea fileb -R file1 file2 file3 /home/jyj (filea,fileb爲文件;file1,file2,file3爲文件夾).

  五、 明天必定要把總後臺的對帳bug解決.

  六、 這幾天要把這篇博客中的全部代碼都改爲插入代碼的格式.

  七、 數據備份:快盤.

【7.6 週一】

  今天完成了總後臺的訂單評價管理的功能,實現對系統全部訂單評價的統計和篩選.學到的東西和遇到的問題總結以下:

  一、 點擊頁面中不一樣的選項按鈕顯示不一樣的子頁面:將兩個不一樣子頁面的相同部分寫成一個新的base,選項按鈕中加a標籤.而後將子頁面分別寫成幾個不一樣的html文件,每一個html文件都繼承這個base,將那個新base中的a標籤連接到新建立的html文件便可.

  二、 html中一個p標籤佔至少一行.

  三、 python字符串內置函數:split
    例:
      >>> s = 'a;b;c;d'
      >>> s.split(';')
      ['a', 'b', 'c', 'd']

  四、 tornado中的塊(block)的用法:

    好比某個base.html中有一段共同的代碼:

1 {% block content %}
2     <div>...</div>
3 {% end %}

    若是想在繼承它的子頁面中的這段代碼的下面插入東西,則要在上面代碼的後面寫上空塊名,好比: 

1 {% block shop %}  
2 {% end %}

    合起來以下:  

1 {% block content %}
2     <div>...</div>
3     {% block shop %}  
4 
5     {% end %}
6 {% end %}

    而後在子頁面中加入塊shop,而後在shop塊中寫代碼便可,以下:

1 {% extends 'base.html'%}
2 {% block shop %}  
3     ...這是子頁面代碼...
4 {% end %}    

    此外還要注意多級繼承時塊的命名和引用,頁面排版格式的問題.

  五、 sqlalchemy用'!= None'來判斷表的某一項不爲空.

  六、 sqlalchemy的like用法:models.Shop.shop_name.like('果%')
    或者:models.Shop.shop_name.like("%{0}%".format(input_name))

  七、 postjson不能傳datetime類型的數據的問題:
      用python的strftime函數轉成字符串再傳.
      用法:data["comment_create_date"] = order.create_date.strftime("%Y-%m-%d %H:%M:%S")
  八、 js中要保持id或class的惟一性,不然容易出現重複執行致使錯亂.

  九、 jquery中$的詳細用法學習,今天由於var變量的時候少了一個$耽誤了好長時間.

  十、 用clone隱藏元素的方法更新頁面的時候,若是遇到一個元素須要根據後臺數據屢次添加怎麼辦?
    解決方法:好比有一個p標籤中有多個img標籤,數量根據後臺傳來的變量i來肯定,那麼在js中只需用一個循環把多個img標籤加入到一個字符串中,而後把這個字         符串append到p標籤便可.

  十一、 js中get方法的使用(參見系統代碼文件superadmin-comment-info.js的initPagesum方法):
    簡單描述以下:假設須要的數據爲page_sum
    ①js中在頁面加載完畢後執行這個函數:

 1 function initPagesum(){
 2     var url = '/super/comment_info?ajaxFlag=1';
 3     $.ajax({
 4         url:url,
 5         type:'get',
 6         success:function(res){
 7             if(res.success){
 8                 page_sum = res.page_sum;
 9                 alert(page_sum);
10             }
11         }
12     });
13 }

    ②後臺對應的get方法要這樣檢查參數:

1 @SuperBaseHandler.check_arguments("ajaxFlag")

    ③後臺要先判斷ajaxFlag的值是否爲1,若是是則用send_success返回數據,不然用render返回數據:

1 if ajaxFlag != '1':
2     self.render('superAdmin/shop-comment-info.html',output_data = output_data,page_sum = page_sum,context=dict(count = {'del_apply':'','all_temp':'','all':'','auth_apply':''},subpage= "info"))
3 else:
4     return self.send_success(page_sum = page_sum)

  十二、 sqlalchemy不能直接用shop_id in [1,2]這樣的用法,而要這樣用:
      shop_id.in_([1,2,3,4])

  1三、 遺留bug彙總:

    ①總後臺'店鋪'欄下左側的選項激活有問題.

    ②總後臺對帳的bug.

  1四、 數據備份:快盤.

7.7 週二

  一、 今日主要任務列表:修復總後臺店鋪頁面中激活左側選項不變成綠色的問題,以及括號中的數據錯誤問題.<---ok
    ①不變綠色問題:superadmin-shop-manage.js加載頁面ready方法中多了這樣一段代碼:

1 if(localStorage.getItem("itemIndex")){
2 $(".shop-manage-nav li").removeClass("active").eq(localStorage.getItem("itemIndex")).addClass("active");
3 }else{
4 localStorage.setItem("itemIndex",0);
5 $(".shop-manage-nav li").removeClass("active").eq(0).addClass("active");
6 }

    ②括號中數據錯誤的問題:
    每一個後臺方法中數據返回的錯誤。
  二、 修復總後臺對帳的bug  <-----ok
  三、 實現點擊一個圖片後顯示大圖:
    思路1:添加圖片的點擊事件,用遮罩層顯示原始大小的圖片。
    思路2:給圖片添加a標籤,打開一個新的窗口顯示原始圖片:<a href="..." target="_blank"><img src="..."/></a>

  四、 要在瀏覽器中查看html加載後,某項後臺數據的值的方法:

1 <div class="admin-left text-right pull-left" data-info="{{context['subpage']}}">

    這樣就能夠在瀏覽器的調試器裏查看data-info的值,耶能夠在js中調用這個值了。

  五、 HTML怎麼給圖片加超連接,點擊圖後在另外一頁打開?

1 <a href="..." target="_blank"><img src="..."/></a>

  六、 整理worktile上daily的文檔的內容到天天日誌中.

  七、 sublime2清除全部書籤:Ctrl+Shift+F2

  八、 完成總後臺評論管理功能!

  九、 html字體加粗:style="font-weight:bold"

  十、 mysql中limit用法:
    select * from table limit m,n
    其中m是指記錄開始的index,從0開始,表示第一條記錄
    n是指從第m+1條開始,取n條。
    例如:select * from tablename limit 2,4
    即取出第3條至第6條,4條記錄

    *mysql分組查詢並用limit的方法:

 1 假若有以下info數據庫: 
 2 +----+------+
 3 | id | name |
 4 +----+------+
 5 | 1 | aa |
 6 | 2 | bb |
 7 | 3 | cc |
 8 | 4 | bb |
 9 | 5 | cc |
10 | 6 | cc |
11 +----+------+
12 執行下列查詢及結果以下:
13 mysql> select * from info group by(name) limit 0,1;
14 +----+------+
15 | id | name |
16 +----+------+
17 | 1 | aa |
18 +----+------+
19 
20 mysql> select * from info group by(name) limit 0,2;
21 +----+------+
22 | id | name |
23 +----+------+
24 | 1 | aa |
25 | 2 | bb |
26 +----+------+
27 
28 mysql> select * from info group by(name) limit 0,3;
29 +----+------+
30 | id | name |
31 +----+------+
32 | 1 | aa |
33 | 2 | bb |
34 | 3 | cc |
35 +----+------+

  十一、 python datetime和time的區別.
    ①字符串轉化爲time類型:

1 >>> import time
2 >>> timestr = "time2009-12-14"
3 >>> t = time.strptime(timestr, "time%Y-%m-%d")
4 >>> print t
5 (2009, 12, 14, 0, 0, 0, 0, 348, -1)
6 
7 >>> type(t)
8 <type 'time.struct_time'>
9 >>>

    ②將time類型轉化爲字符串:

1 now_time = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))

    ③time類型與datetime類型的轉換:

1 >>> import datetime
2 >>> d = datetime.datetime(* t[:6])
3 >>> print d
4 2009-12-14 00:00:00
5 
6 >>> type(d)
7 <type 'datetime.datetime'>
8 >>> 

    ④經常使用格式化符號:

 1   %a 星期幾的簡寫 Weekday name, abbr.
 2   %A 星期幾的全稱 Weekday name, full
 3   %b 月分的簡寫 Month name, abbr.
 4   %B 月份的全稱 Month name, full
 5   %c 標準的日期的時間串 Complete date and time representation
 6   %d 十進制表示的每個月的第幾天 Day of the month
 7   %H 24小時制的小時 Hour (24-hour clock)
 8   %I 12小時制的小時 Hour (12-hour clock)
 9   %j 十進制表示的每一年的第幾天 Day of the year
10   %m 十進制表示的月份 Month number
11   %M 十時製表示的分鐘數 Minute number
12   %S 十進制的秒數 Second number
13   %U 第年的第幾周,把星期日作爲第一天(值從0到53)Week number (Sunday first weekday)
14   %w 十進制表示的星期幾(值從0到6,星期天爲0)weekday number
15   %W 每一年的第幾周,把星期一作爲第一天(值從0到53) Week number (Monday first weekday)
16   %x 標準的日期串 Complete date representation (e.g. 13/01/08)
17   %X 標準的時間串 Complete time representation (e.g. 17:02:10)
18   %y 不帶世紀的十進制年份(值從0到99)Year number within century
19   %Y 帶世紀部分的十制年份 Year number
20   %z,%Z 時區名稱,若是不能獲得時區名稱則返回空字符。Name of time zone
21   %% 百分號

  十二、 獲取昨天的日期:lastday = datetime.datetime.now() - datetime.timedelta(1)

  1三、 mysql 從datetime類型中取日期:
      在mysql中,我要取出當天錄入的記錄。裏面錄入時間: AddTime是datetime類型,假設其值爲:2007-08-06 10:12:22
      select * from table1 where AddTime='2007-08-06'
      這裏的時間AddTime要經過什麼函數處理才能獲得日期部分,從而能夠和後面的日期可以比較。
      方法①:select * from table1 where TO_DAYS(AddTime)=TO_DAYS(NOW())
      方法②:SELECT * from taffair where date_format(TAffairDate,'%Y-%m-%d')='2007-04-04'

  1四、 sqlalchemy distinct用法:persons = self.session.query(models.BalanceHistory.customer_id).distinct()
      或:persons = self.session.query(models.BalanceHistory).distinct(models.BalanceHistory.customer_id)
  1五、 jQuery中this與$(this)的區別

  1六、 MySQL 查詢某個字段不重複的全部記錄:

 1 //假設如今有以下6條記錄 表名叫info
 2 +------+----+
 3 | name | id |
 4 +------+----+
 5 | aa | 1 |
 6 | bb | 2 |
 7 | cc | 3 |
 8 | bb | 4 |
 9 | cc | 5 |
10 | cc | 6 |
11 +------+----+
12 //如今想從這6條記錄中查詢全部name不重複的記錄
13 select distinct name,id from book這樣是不能夠的 由於distinct只能做用於一個字段
14 //答案: 
15 select a.* from info a right join (
16 select min(id) from info group by name) b on b.id = a.id
17 where a.id is not null

  1七、 ?sqlalchemy不能對datetime類型用distinct(這是什麼問題咧???)
    用老辦法:利用存在性數組,每次搜索是否在數組之中。
    缺陷:嚴重影響性能!有必要研究一下sql的distinct算法實現。
    根本緣由仍是js動態綁定的問題!

7.8 週三】

  一、 今天任務:完成店鋪後臺的銷售統計;總後臺對帳仍然有bug且查詢效率很低:要重構代碼。

  二、 echarts好酷炫.

  三、 echarts簡析(標準條形圖)
    1.圖表數據都包含在一個Object對象option中

 1 option = {
 2     title : {  //圖表標題和副標題
 3         text: '世界人口',
 4         subtext: '數據來自網絡'
 5     },
 6     tooltip : {  //數據提示框
 7         trigger: 'axis'
 8     },
 9     legend: {  //圖表圖例
10         data:['2011年', '2012年']
11     },
12     toolbox: {  //圖表的右上角的工具箱
13         show : true,
14         feature : {  //控制顯示哪些工具
15            mark : {show: true},
16            dataView : {show: true, readOnly: false},
17            restore : {show: true},
18            saveAsImage : {show: true}
19         }
20     },
21     calculable : true,
22     xAxis : [  //x軸的屬性及數據
23         {
24             type : 'value',
25             boundaryGap : [0, 0.01]
26         }
27     ],
28     yAxis : [  //y軸的屬性及數據
29         {
30              type : 'category',
31             data : ['巴西','印尼','美國','印度','中國','世界人口(萬)']
32         }
33     ],
34     series : [  //圖表中顯示的數據,有若干個系列,數量及名稱和legend的data對應
35         {
36             name:'2011年',
37             type:'bar',
38             data:[18203, 23489, 29034, 104970, 131744, 630230]
39         },
40         {
41           name:'2012年',
42              type:'bar',
43              data:[19325, 23438, 31000, 121594, 134141, 681807]
44         }
45     ]
46 }; 47

    2.option內容分析:
    (1)title:圖表標題,每一個圖表最多僅有一個標題控件,每一個標題控件可設主副標題。
      text(主標題)
      subtext(副標題)

    (2)tooltip:提示框,經常使用於展示更詳細的數據.
      trigger:觸發類型,默認數據觸發,可選爲:'item' | 'axis'

    (3)legend:圖例,每一個圖表最多僅有一個圖例。
      orient:佈局方式,默認爲水平佈局,可選爲:'horizontal' | 'vertical'
      x:水平安放位置,默認爲全圖居中,可選爲:'center' | 'left' | 'right' | {number}(x座標,單位px)
      y:垂直安放位置,默認爲全圖頂端,可選爲:'top' | 'bottom' | 'center' | {number}(y座標,單位px)
      backgroundColor:圖例背景顏色,默認透明
      data:圖例內容數組,數組項一般爲{string},每一項表明一個系列的name,默認佈局到達邊緣會自動分行(列),傳入空字符串''可實現手動分行(列)。
      使用根據該值索引series中同名系列所用的圖表類型和itemStyle,若是索引不到,該item將默認爲沒啓用狀態。
      如需個性化圖例文字樣式,可把數組項改成{Object},指定文本樣式和個性化圖例icon,格式爲

1 {
2   name : {string},
3   textStyle : {Object},
4   icon : {string}
5 }

    (4)toolbox:工具箱,每一個圖表最多僅有一個工具箱.
      orient:佈局方式,默認爲水平佈局,可選爲:'horizontal' | 'vertical' .
      x:水平安放位置,默認爲全圖居中,可選爲:'center' | 'left' | 'right' | {number}(x座標,單位px)
      y:垂直安放位置,默認爲全圖頂端,可選爲:'top' | 'bottom' | 'center' | {number}(y座標,單位px)
      backgroundColor:工具箱背景顏色,默認透明
      padding:工具箱內邊距,單位px,默認各方向內邊距爲5,接受數組分別設定上右下左邊距,同css.
      itemGap:各個item之間的間隔,單位px,默認爲10,橫向佈局時爲水平間隔,縱向佈局時爲縱向間隔.
      itemSize:工具箱icon大小,單位(px),默認16px
      color:工具箱icon顏色序列,循環使用,同時支持在具體feature內指定color.

1 feature : {
2   mark : {show: true},
3   dataView : {show: true, readOnly: false},
4   magicType : {show: true, type: ['line', 'bar', 'stack', 'tiled']},
5   restore : {show: true},
6   saveAsImage : {show: true}
7 }

    (5)xAxis : [
      {
        type : 'value'
      }
     ]
    (6)yAxis : [
      {
        type : 'category',
        data : ['週一','週二','週三','週四','週五','週六','週日']
      }
     ]
    (7)series(直角系):驅動圖表生成的數據內容數組,數組中每一項爲一個系列的選項及數據,其中個別選項僅在部分圖表類型中有效,請注意適用類型。
      stack:組合名稱,雙數值軸時無效,多組數據的堆積圖時使用,eg:stack:'group1',則series數組中stack值等於'group1'的數據作堆積計算。

    注:在series後面再加以下的一個color數組,則echarts中的圖表元素的顏色會根據這個數組自動循環設置。

      color: ['#b6a2de','#2ec7c9','#5ab1ef','#ffb980','#d87a80',
         '#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa',
         '#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050',
         '#59678c','#c9ab00','#7eb00a','#6f5553','#c14089']

  四、 jQuery 遍歷 - siblings() 方法:
    例:$("p").siblings(".selected") 查找每一個p元素的全部類名爲 "selected" 的全部同胞元素.

  五、 mysql比較時間:select create_time from check_profit where date_format(create_time,"%Y-%m-%d")<'2015-07-01';

  六、 導出數據庫中某張表的結構及數據:mysqldump -uroot -pdbpasswd dbname test>db.sql;
    導入的話仍是用source,導入的時候不用刪除表結構,直接導入sql便可。導入後會自動覆蓋舊數據,不用擔憂錯亂的問題。

  七、 python獲取今天的0:0:0:
      now_time = time.localtime(time.time())
      now_time = datetime.datetime(*now_time[:6])
      now_time = datetime.datetime(now_time.year, now_time.month, now_time.day, 0,0,0)
    獲取昨天的0:0:0:
      last_time = now_time - datetime.timedelta(1)

  八、 改變圖表標題下方三個選項按鈕的激活狀態,而且選擇不一樣按鈕的時候圖表的時間選項發生變化:
    (1)html中寫以下代碼:

1 <div class="change-box">
2   <ul id="order_trend_change" class="sell-change-list pull-left">
3     <li data-id="1"><a href="javascript:;" class="text-grey3">訂單量/個</a></li>
4     <li data-id="2"><a href="javascript:;" class="text-grey3">訂單金額/元</a></li>
5   </ul>
6 </div>

    (2)js中添加以下代碼:

 1 $(document).ready(function(){
 2   $('.change-list li').on('click',function(){
 3     var $this=$(this);
 4     $this.addClass('active').siblings('li').removeClass('active');
 5   });
 6   $('.change-list').each(function(){
 7     var $this=$(this);
 8     $this.find('li').eq(0).addClass('active');
 9   });
10 });

    (3)css中有以下屬性:

1 .sell-change-list{margin-left:60px;margin-top: 10px;}
2 .sell-change-list li{border-left:2px solid #fff;padding-left:14px;float:left;margin-right: 30px;}
3 .sell-change-list li.active{border-color:#44b549;}
4 .sell-change-list li.active a{color:#44b549;}

  九、 css的padding:
    padding 屬性設置元素的內邊距。
    padding 屬性定義元素邊框與元素內容之間的空間。
    該屬性可採起 4 個值:
      若是規定一個值,好比 div {padding: 50px} - 全部四個邊的 padding 都是 50 px。
      若是規定兩個值,好比 div {padding: 50px 10px} - 上下內邊距是 50 px,左右內邊距是 10 px。
      若是規定三個值,好比 div {padding: 50px 10px 20px} - 上內邊距是 50 px,左右內邊距是 10 px,下內邊距是 20 px。
      若是規定四個值,好比 div {padding: 50px 10px 20px 30px} - 上內邊距是 50 px,右內邊距是 10 px,下內邊距是 20 px,左內邊距是 30 px。

  十、 js時間操做:
    (1)獲取當前日期及其餘操做:

 1 var myDate = new Date();
 2 myDate.getYear(); //獲取當前年份(2位)
 3 myDate.getFullYear(); //獲取完整的年份(4位,1970-????)
 4 myDate.getMonth(); //獲取當前月份(0-11,0表明1月)
 5 myDate.getDate(); //獲取當前日(1-31)
 6 myDate.getDay(); //獲取當前星期X(0-6,0表明星期天)
 7 myDate.getTime(); //獲取當前時間(從1970.1.1開始的毫秒數)
 8 myDate.getHours(); //獲取當前小時數(0-23)
 9 myDate.getMinutes(); //獲取當前分鐘數(0-59)
10 myDate.getSeconds(); //獲取當前秒數(0-59)
11 myDate.getMilliseconds(); //獲取當前毫秒數(0-999)
12 myDate.toLocaleDateString(); //獲取當前日期
13 var mytime=myDate.toLocaleTimeString(); //獲取當前時間
14 myDate.toLocaleString( ); //獲取日期與時間

  十一、 js將字符串轉化成日期的方法:

1 var str ='2015-01-01 23:13:15';
2 str = str.replace(/-/g,"/");
3 var date = new Date(str );

  十二、 js判斷某天是這年的第幾周:

 1 function WeekNumOfYear(date) {   
 2     var yy = date.getFullYear();
 3     var day = date.getDay();
 4 
 5     var date0 = new Date(yy,0,1);
 6     var date_diff = DateDiff(date,date0);
 7     if(date_diff < 7-day){
 8         week_num = 1;
 9     }
10     else{
11         var week_num = Math.ceil((date_diff-(7-day))/7)+1;
12     }
13 
14     return week_num;
15 }

  1三、 js ceil() 方法可對一個數進行上舍入。
    Math.ceil(x)

  1四、 js round() 方法可把一個數字舍入爲最接近的整數。

  1五、 js獲取當前日期的先後N天日期的方法:

  1 // 獲取當前日期的先後N天日期(返回值爲Date類型)(N<=28):
  2 function GetDateN(date,AddDayCount) 
  3 { 
  4     var dd = new Date(2015,1,1);  //此處若是使用new Date(),則會出現詭異的錯誤
  5 
  6     var date_year = date.getFullYear();
  7     var date_month = date.getMonth()+1;
  8     var date_date = date.getDate();
  9 
 10     dd.setDate(date_date);
 11     dd.setMonth(date_month - 1);
 12     dd.setFullYear(date_year);
 13 
 14     var n_flag;
 15     var is_leap;
 16 
 17     if(AddDayCount >= 0){
 18         n_flag = 1;
 19     }
 20     else{
 21         n_flag = 0;
 22     }
 23 
 24     if((date_year % 4 == 0 && date_year % 100 != 0) || (date_year % 400 == 0)){
 25         is_leap = 1;
 26     }
 27     else{
 28         is_leap = 0;
 29     }
 30 
 31     switch(n_flag){
 32         case 1:
 33             if (date_month == 2){
 34                 switch(is_leap){
 35                     case 1:
 36                         if(date_date + AddDayCount > 29){
 37                             dd.setMonth(date_month);
 38                             dd.setDate(date_date+AddDayCount - 29);
 39                         }
 40                         else{
 41                             dd.setDate(date_date + AddDayCount);
 42                         }
 43                     break;
 44 
 45                     case 0:
 46                         if(date_date + AddDayCount > 28){
 47                             dd.setMonth(date_month);
 48                             dd.setDate(date_date+AddDayCount - 28);
 49                         }
 50                         else{
 51                             dd.setDate(date_date + AddDayCount);
 52                         }
 53 
 54                     break;
 55                 }
 56             }
 57             else if ((date_month == 1 || date_month == 3 || date_month == 5 || date_month == 7 || date_month == 8 || date_month == 10 ) && date_date + AddDayCount > 31){
 58                 dd.setMonth(date_month);
 59                 dd.setDate(date_date+AddDayCount - 31);    
 60             }
 61             else if(date_month == 12 && date_date + AddDayCount > 31){
 62                 dd.setDate(date_date+AddDayCount - 31);
 63                 dd.setMonth(0);
 64                 dd.setFullYear(date_year + 1);
 65             }
 66             else if ((date_month == 4|| date_month == 6 || date_month == 9 || date_month == 11) && date_date + AddDayCount > 30){
 67                 dd.setMonth(date_month);
 68                 dd.setDate(date_date+AddDayCount - 30);    
 69             }
 70             else{
 71                 dd.setDate(date_date + AddDayCount);
 72             }
 73         break;
 74         case 0:
 75             if ((date_month == 3) && date_date + AddDayCount <= 0){
 76                 switch(is_leap){
 77                     case 1:
 78                         if(date_date + AddDayCount <= 0){
 79                             dd.setMonth(date_month - 2);
 80                             dd.setDate(date_date + 29 + AddDayCount);
 81                         }
 82                         else{
 83                             dd.setDate(date_date + AddDayCount);
 84                         }
 85                     break;
 86 
 87                     case 0:
 88                         if(date_date + AddDayCount <= 0){
 89                             dd.setMonth(date_month - 2);
 90                             dd.setDate(date_date + 28 + AddDayCount);
 91                         }
 92                         else{
 93                             dd.setDate(date_date + AddDayCount);
 94                         }
 95 
 96                     break;
 97                 }
 98             }
 99             else if ((date_month == 2 || date_month == 4 || date_month == 6 || date_month == 8 || date_month == 9 || date_month == 11 ) && date_date + AddDayCount <= 0){
100                 dd.setMonth(date_month - 2);
101                 dd.setDate(date_date + 31 + AddDayCount);
102             }
103             else if(date_month == 1 && date_date + AddDayCount <= 0){
104                 dd.setFullYear(date_year - 1);
105                 dd.setMonth(11);
106                 dd.setDate(date_date + 31 + AddDayCount);
107             }
108             else if ((date_month == 5|| date_month == 7 || date_month == 10 || date_month == 12) && date_date + AddDayCount <= 0){
109                 dd.setMonth(date_month - 2);
110                 dd.setDate(date_date + 30 + AddDayCount);
111             }
112             else{
113                 dd.setDate(date_date + AddDayCount);
114             }
115         break;
116     }
117     
118     // 
119     var y = dd.getFullYear(); 
120     var m = (dd.getMonth()+1)<10?"0"+(dd.getMonth()+1):(dd.getMonth()+1);//獲取當前月份的日期,不足10補0
121     var d = dd.getDate()<10?"0"+dd.getDate():dd.getDate(); //獲取當前幾號,不足10補0
122     var str = y+"-"+m+"-"+d+" 00:00:00"; 
123     str = str.replace(/-/g,"/");
124     var new_date = new Date(str);
125     return new_date;
126 }

  16. firebug下能夠成功使用console.log()

  17. css居中問題:
    div居中:
      margin: 0 auto;
    text居中:
      text-align:center;

  18. ?js深拷貝和淺拷貝問題.

  19. sublime快捷鍵:Ctrl+Shift+上/下鍵:將一行上移/下移.

  20. js計算兩個日期的天數差:

 //計算天數差的函數,通用  
function  DateDiff(sDate1,  sDate2){    
    var  oDate1,  oDate2,  iDays ;
    var dd1,dd2,mm1,mm2,yy1,yy2;
    dd1 = sDate1.getDate();
    mm1 = sDate1.getMonth();
    yy1 = sDate1.getFullYear();
    dd2 = sDate2.getDate();
    mm2 = sDate2.getMonth();
    yy2 = sDate2.getFullYear();

    oDate1  =  new  Date(yy1,mm1,dd1) ;   
    oDate2  =  new  Date(yy2,mm2,dd2) ; 
    iDays  =  parseInt(Math.abs(oDate1  -  oDate2)/1000/60/60/24);    //把相差的毫秒數轉換爲天數  
    return  iDays;  
}

  2一、 今日備份:快盤。

 

 [7.14 週二]

  昨天從安徽黃山旅遊5天回來,今天是回來的第一天上班。主要完成的工做爲:店鋪後臺銷售統計的前端日/周/月的時間顯示與選擇功能,爲以後的後端數據查詢與分析功能奠基了基礎。

  一、 bug:總後臺店鋪評論不該該包括系統自動評論的訂單
    修改方案:把狀態爲7(系統自動評價)的訂單去掉。
  二、 判斷閏年:if((year%4==0&&year%100!=0)||(year%400==0))

    即:年份能被4整除但不能被100整除,或者能被400整除。
  三、 js 單獨set年月日時要先set month再set date
  四、 js date類的setMonth方法的詭異問題(setMonth後月份順延問題):

    若是原來date的月份是偶數月,則從新setmonth後月份會比正確值多1,而奇數月不會有這個問題。
    如:date原來爲2015-08-31,通過date.setMonth(8)之後,date變成了2015-10-01,而不是2015-09-01。
    解決方案:在建立date的時候不要使用空的構造函數:var date = new date();
    而要用相似於這樣的構造函數:var date = new date(2015,1,1);
    這樣問題就會解決。
  五、 js中的整除運算:
    Math.ceil(count / pagesize);   //向上整除 4/3=2;
    Math.floor(count / pagesize);   //向下整除 4/3=1;
  六、 建立日期對象的方法之一:
    var date = new Date(2015,0,1,23,59,59);
    其中0表示是1月份。
  七、 git本地倉庫切換分支後,sublime中的代碼會自動更新到切換後的分支。
  八、 發現最近常常和mysql、python、js的時間類型打交道,而用到的時候又不是很熟悉,並且很是容易搞混,因此要作個總結:

  (1)三種日期類型之間的相互轉化的方法:
    ①MySQL datetime類型——>python的datetime類型
    ②python的datetime類型——>MySQL datetime類型
    ③js的date類型——>python的datetime類型
    ④python的datetime類型——>js的date類型
  (2)同種語言日期類型與字符串的相互轉化:
    ①python中日期字符串——>python datetime類型
    ②python datetime類型——>字符串
    ③js中日期字符串——>js date類型
    ④js date類型——>js字符串
    ⑤MySQL中日期字符串——>MySQL datetime類型
    ⑥MySQL datetime類型——>MySQL字符串\
  (3)同種語言時間戳和日期類型的相互轉化:
    ①python時間戳——>python datetime類型
    ②python datetime類型——>python時間戳
    ③js時間戳——>js datetime類型
    ④js datetime類型——>js時間戳
    ⑤MySQL時間戳——>MySQL datetime類型
    ⑥MySQL datetime類型——>MySQL時間戳
  九、 店鋪的水果信息在Fruit表中存。
  十、 字段關聯的時候的查詢方法。

  十一、 今日備份:快盤

 

 【7.15 週三】

  今天主要作的工做是繼續寫店鋪後臺的銷售統計的功能。昨天已經完成了前臺最重要的功能之一:顯示並可以選擇不一樣的日/周/月,今天作的工做主要是數據需求和數據庫的分析工做。

  一、 bug:總後臺訂單時間和送達時間統計的數據徹底同樣
     解決方法:測試的時候發現報錯:'KeyError:24',通過排查發現是superadmin.py中orderstatic類中的數組下標越界問題,數組最大的下標爲23,可是數據會出現24的下標,從而致使錯誤。
     改爲這樣便可:

1  if order[0] == 1:  # 當即送收貨時間估計
2     if order[1].hour + (order[1].minute+order[3])//60 == 24:
3       data[0] += 1
4     else:
5       data[order[1].hour + (order[1].minute+order[3])//60] += 1

  二、 今日任務數據需求與數據庫分析:
    (1)銷量排行:按商品類目排序 數據需求分析
      用戶所選時間段(某天,某周,或某個月)內的該店鋪(self.current_shop)的不一樣類目的商品的總銷售額、該類目下的全部小類商品的銷售額,以及數據的排序(按照類目總銷售額從大到小排序)
      ①查詢某個店鋪全部水果的類目:

1 select distinct fruit_type.name from fruit_type,fruit where fruit_type.id = fruit.fruit_type_id and fruit.shop_id = 1203;

      ②查詢某個店鋪的某個水果屬於什麼類目:

1 select fruit_type.name from fruit_type,fruit where fruit.fruit_type_id = fruit_type.id and fruit.shop_id = 1203 and fruit.name = '青蘋果';

      ③查詢某個店鋪的全部水果名稱:

1 select name from fruit where shop_id = 1203;

      ④從order表中查詢出特定的一天某個店鋪的全部有效訂單(status字段的值大於等於5)的fruits字段:

1 select fruits from senguocc.order where shop_id = 1203 and status >= 5 and ((create_date like "2015-07-15%" and today = 1) or (date_sub(create_date,interval -1 day) like "2015-07-15%" and today = 2) );

      ⑤從order表中查詢出某個日期區間內某個店鋪的全部有效訂單(status字段的值大於等於5)的fruits字段(好比2015-07-15和2015-07-16兩天的):

1 select fruits from senguocc.order where shop_id = 1203 and status >= 5 and ( (create_date >= "2015-07-15" and date_sub(create_date,interval 1 day) < '2015-07-16' and today = 1) or (date_sub(create_date,interval -1 day) >= "2015-07-15" and create_date < "2015-07-16" and  today = 2) );

      ⑥查詢某個店鋪全部水果類目中分別有多少種水果:

1 shop_type_num_list = []
2 for shop_type_name in shop_all_type_name:
3     tmp = {}
4     shop_type_name = shop_type_name[0]
5     tmp["type_name"] = shop_type_name
6     tmp["type_num"] = self.session.query(models.FruitType).join(models.Fruit).filter(models.Fruit.shop_id == self.current_shop.id,models.FruitType.name == shop_type_name).count()
7     shop_type_num_list.append(tmp)

      ⑦把⑥中查到的fruits字段中的每一個單種商品的名稱、數量、計價方式的單價分離出來,並計算出每一個fruits中每一個單種商品的銷售額。

      *將fruits字段的字符串先轉化爲字典類型,而後從字典裏面取值
      *注:訂單的status字段的值大於等於5的訂單才能算銷售額
      *是否是應該有個運費收入
      *order表有一個today字段,today=1表示送貨時間是‘今天’(即和order的create_date在同一天),today=2表示送貨時間是'明天'(即在order的create_date的後一天)

      *用戶不能本身建立新的類目,若是用戶的商品不在現有的類目中,則只能歸爲'其餘'類。
    (2)銷量排行:按商品名稱排序 數據需求分析
      用戶所選時間段(某天,某周,或某個月)內的該店鋪(self.current_shop)的不一樣名稱的商品的銷售額,以及數據的排序(按照商品銷售額從大到小排序)
    (3)單種水果的銷售額統計
    (4)單個類目水果的銷售額統計

  三、 python如何將字符串轉換成字典dict類型:
    用eval()或exec()函數實現:
      >>> user
      "{'name' : 'jim', 'sex' : 'male', 'age': 18}"
      >>> b=eval(user)
      >>> b
      {'age': 18, 'name': 'jim', 'sex': 'male'}
      >>> exec("c="+user)
      >>> c
      {'age': 18, 'name': 'jim', 'sex': 'male'}


  四、 mysql date_sub()函數舉例:
    假現在天是2013年5月20日。
    date_sub('2012-05-25',interval 1 day) 表示 2012-05-24
    date_sub('2012-05-25',interval 0 day) 表示 2012-05-25
    date_sub('2012-05-25',interval -1 day) 表示 2012-05-26
    date_sub('2012-05-31',interval -1 day) 表示 2012-06-01
    date_sub(curdate(),interval 1 day) 表示 2013-05-19
    date_sub(curdate(),interval -1 day) 表示 2013-05-21
    date_sub(curdate(),interval 1 month) 表示 2013-04-20
    date_sub(curdate(),interval -1 month) 表示 2013-06-20
    date_sub(curdate(),interval 1 year) 表示 2012-05-20
    date_sub(curdate(),interval -1 year) 表示 2014-05-20

  五、 python獲取當前時間:now = datetime.datetime.now()
    獲取當前時間的年月日:now_date = datetime.datetime(now.year,now.month,now.date)

  六、 這樣解決以前的echarts沒有知足要求的堆積圖表的難題:
    第一步先把全部類目的水果的總銷售額用條形圖顯示出來;
    第二步爲每一個類目的條形圖添加點擊事件,當點擊的時候彈出新的圖層顯示該類目不一樣種類水果的詳細銷售額。

  七、 mysql日期或時間類型能夠直接與日期或時間字符串比較大小。
    好比今天是2015-07-15,則:

      select curdate()>'2015-07-10'的值爲1,select curdate()>'2015-07-19'的值爲0.
      select now() > '2015-07-10'的值爲1,select now() < '2015-07-10'的值爲0.

  八、 今日備份:快盤

  【7.16 週四】

  今天完成的主要工做有:店鋪後臺銷售統計的按照商品類目統計和按照商品名稱統計的功能已經基本實現。

  一、 python的下面這段代碼執行的時候會出現錯誤: now_date = datetime.datetime(now.year,now.month,now.date) TypeError: an integer is required (got type builtin_function_or_method)

1 now = datetime.datetime.now()
2 now_date = datetime.datetime(now.year,now.month,now.date)

    解決方法:把now.date改成now.day便可。

  二、 sqlalchemy join查詢的總結:
    (1)當兩個表之間只有一個外鍵的時候,這樣用:

1 session.query(User).join(Address).\
2 ...
3     filter(Address.email_address=='jack@google.com').\
4 .
5     all() 

    (2)當兩個表之間沒有外鍵或者有不止一個外鍵的時候,這樣用:

1  query.join(Address,User.id==Address.user_id)# 明確的條件
2  query.join(User.addresses)# 指定從左到右的關係
3  query.join(Address,User.addresses)    #一樣,有明確的目標
4  query.join('addresses') # 一樣,使用字符串

        outerjoin()和join()用法相同:

1 query.outerjoin(User.addresses)   # LEFT OUTER JOIN

  三、 兩個頗有用的前端網站:bootstrap,iconfont

  四、 python將字符串轉化爲datetime類型:

1 end_date_str = '2015-07-16'
2 end_date = datetime.datetime.strptime(end_date_str,'%Y-%m-%d')

  五、 python計算當前時間向後10天的時間:

1 d1 = datetime.datetime.now()
2 d2 = d1 + datetime.timedelta(days =10)

  六、 python遍歷取得字典的value的方法:

1 for key in dic_list:
2     value = dic_list[key]

    注:這裏的'key'能夠寫成其餘的字符,好比aa,bb等。
      此外字典能夠用變量當作索引。

  七、 python 只得到字典中全部鍵的名字到列表中:

1 d={'a': 2, 'b': 3, 'd': 4}
2 dlist=list(d.keys())

    用字典的keys方法得到全部鍵的名字,python3須要轉換爲list,python2直接爲list

    (是否是還有個values方法??)
  八、 js給後臺傳的參數設計:

    (1)action,5個取值:'all','type','name','single_type','single_name'
    (2)type,3個取值:'day','week','month'
    (3)start_date
    (4)end_date
    注:感受type沒有必要要.

  九、 python列表排序:

1 listaa.sort(key = lambda aa_item:len(aa_item),reverse=True)  #按照列表listaa的每一項的長度的降序排列.

  十、 今天遇到一個問題:在js中將Date類型值經過postJson傳給python後臺後,發現這個值莫名其妙地少了一天,後來通過學長的提醒,發現應該是由於js和python所用時區不同,從而致使了日期不一致的問題。
    解決方案:在js中經過postJson傳Date值前,先將它轉化成字符串再傳。自編字符串轉化函數:

1 function getDateStr(date){
2     var y = date.getFullYear();
3     var m = (date.getMonth()+1)<10?"0"+(date.getMonth()+1):(date.getMonth()+1);//獲取當前月份的日期,不足10補0
4     var d = date.getDate()<10?"0"+date.getDate():date.getDate(); //獲取當前幾號,不足10補0
5     var str = y+"-"+m+"-"+d;
6     return str;
7 }

  十一、 研究一下echarts條形圖的點擊事件
  十二、 js中for(var i = 0;i < data.length;i++)和for(var i in data)的區別。

  1三、 今日備份:快盤

  [7.17 週五]

  一、 今天主要任務:店鋪後臺銷售統計。

  二、 問題:圖表所在的div的高度不能根據圖表內容的增多自動增高

    解決方法:在圖表init以前就發post請求得到要顯示的數據,而後根據數據的多少動態設置div的高度,而後再init圖表便可。
    設置div高度的方法:

1 $("#div-name").css("height",50*data.length + 'px');

  三、 今天用到的技術:
    (1)echarts條形圖的點擊事件
    (2)遮罩層的實現
    (3)下拉選項按鈕
    (4)echarts圖表的屬性設置

  四、 頁面刷新後圖表的y座標軸的文字被遮擋了一部分,並且橫座標的值也沒有顯示出來。
    問題所在:options的series[0]的itemStyle屬性設置的問題
    解決方案:
      原來的echarts的itemStyle屬性爲:

1 itemStyle : { normal: {label : {show: true, position: 'insideRight'}}}

      改成以下這樣便可解決問題:

 1 itemStyle : { 
 2     normal: {
 3         label : {
 4             show: true, 
 5             position: 'right',
 6             textStyle : {
 7                 fontWeight : 'bold'
 8             }
 9         }
10     }
11 }    

  五、 js把數值字符串轉化爲浮點型並保留兩位小數(後來發現toFixed最後的結果的類型是字符串):

1 var price = parseFloat("123.4567").toFixed(2);

  六、 發現個問題:若是echarts圖表所在的div的高度過小了那麼echarts也顯示不出來。

  七、 今天下午遇到一個奇怪的問題:電腦過一個多小時彈出一個對話框,而後強制自動關機一次,很不爽。。CPU也不熱呀,要找到緣由。並且這幾天鍵盤還有好幾個鍵失靈,目測是短路了,找時間去修一修。

  八、 問題:echarts圖表能顯示最大值最小值,但就是顯示不出來平均值。
    通過反覆測試發現:echarts在求平均值的時候居然不能對浮點數求平均值,只能是整數。
    最後才發現:原來js對浮點數執行toFixed方法的結果是字符串,並非數值型,這才致使了不能求平均值。
    好比:var aa = 123.456.toFixed(2);則用typeof aa能夠發現aa的類型爲string,並非浮點型,要把aa在轉換成浮點型,要用parseFloat(aa)函數。
    把toFixed方法執行過的結果先用parseFloat強制轉換成浮點型,再push給echarts的series的data,則能夠解決問題。

  九、 這幾天公司常常斷網,要下個echarts的離線文檔,防止斷網的時候不能看。

  [7.19 週日]

  今天把店鋪後臺的銷售統計功能成功完成!

  一、 標籤屬性中添加的onclick事件傳遞參數的問題,傳遞的參數是整個標籤嗎?

  二、 下拉選擇按鈕的實現總結。

    這個實現使用的bootstrap的控件元素。

    ①在css中編寫以下樣式:

 1 .mlf20{margin-left: 20px;}
 2 .dropdown-menu{overflow: hidden;max-height: 210px;overflow-y: auto;}
 3 .category-list>li{float: left;width: 25%;}
 4 .cate-title{font-size: 14px;color: #999;height: 28px;line-height: 28px;float: left;margin-right: 5px;}
 5 .slide-down-select{display:inline-block;width:100%;background:#fff;color:#000;border:1px solid #ddd;margin-left:0;}
 6 .slide-down-select .slide-btn{height: 24px;line-height: 24px;display: block;border: none;outline: none;width: 100%;}
 7 .slide-down-select em{font-style:normal;display:inline-block;width:110px;font-size:14px;overflow:hidden;padding-left: 10px;text-align: left;}
 8 .dropdown-toggle{padding:0 4px;}
 9 .dropdown-menu li{width:100%;padding:0;}
10 .dropdown-menu .item{padding-left:14px;}
11 .dropdown-menu li a:hover{color:#fff;background-color: #6ba4ef;}
12 .caret{margin-top:10px;color: #c6c6c6;}
13 .borderc{border: 1px solid #e7e7eb;}
14 .pointer{cursor: pointer;}
15 .min80{min-width: 80px;}
16 .mt2{margin-top: 2px;}
17 .txt-center{text-align: center !important;}
18 .txt-left{text-align: left !important;}
19 .hig{border: 1px dashed #ff6666 !important;}
20 .no-title{font-size: 20px;text-align: center;margin-top: 40px;color: #333;}
21 
22 .pull-left{float:left !important;}
23 .w130{width:130px !important;}

    ②在html中要加入下拉選擇按鈕的地方寫以下代碼,其中最外的是li元素,第一個div是選擇按鈕前的提示文字,第二個div中:button表明下拉選擇按鈕最上面顯示的按鈕,em標籤表明強調;button下面的ul標籤是隱藏的幾個按鈕,當點擊最上方按鈕的時候隱藏的按鈕出現,ul的標籤內容是在js中動態添加的。      

 1    <li> 
 2         <div class="tit cate-title">選擇商品類目:</div>
 3         <div class="dropdown slide-down-select pull-left w130">
 4                 <button class="btn btn-default dropdown-toggle area height25 slide-btn" type="button" id="dropdownMenu3" data-toggle="dropdown">
 5                     <em class="pull-left filter_status" id="first_type"></em>
 6                     <span class="caret pull-right no-margin-left rotate0"></span>
 7                 </button>
 8                 <ul class="dropdown-menu dropdown-menu-right w130 condition-list" role="menu" aria-labelledby="dropdownMenu3" id="currentTypeName">
 9                 </ul>
10         </div>
11     </li>

    ③在js中,爲button及ul添加內容及添加點擊事件:

    添加內容:

 1          
2
$("#first_type").text(type_max); 3 6 $("#currentTypeName").empty(); 7
8
9 for(var i = 0;i < all_type.length;i++){ 10 11 var type_id = "type"+i; 12 var item = '<li>' 13 +'<a class="item" id={{type_id}} onclick="onTypeItemClick({{type_id}})">{{type_name}}</a>' 14 '</li'; 15 var render = template.compile(item); 16 17 var type_name = all_type[i]; 18 var list_item= render({ 19 type_id:type_id, 20 type_name:type_name 21 }); 22 $("#currentTypeName").append(list_item); 23 24 }

    點擊事件:

1 function  onTypeItemClick(type_id){
2     var first_type = $("#"+type_id.id).text();
3     $("#first_type").text(first_type);
4     
5 
6 }

  三、 爲echarts的series動態添加新的系列:

1 options.series.push({name:"aaa",stack:'總量',type:'bar',data:[220, 232, 101, 234, 190]});

  四、 js遍歷object的方法:

1 var obj = {"name":"jyj","age":22};
2 for(var key in obj){
3   console.log(key);
4 }

  輸出結果:
    name
    age

  若是改爲這樣:

1 var obj = {"name":"jyj","age":22};
2 for(var e in obj){
3   console.log(obj[e]);
4 }

  輸出結果:
    jyj
    22 

  五、 echarts渲染以前xAxis的data不能爲空,不然會出錯。

  六、 幾個小問題:
  (1)考慮到數據量大的時候的顯示問題,爲下拉選項框和前兩個圖表增長滾動條功能。     ---ok
  (2)前兩個圖表的每一個條的高度小一點,20px左右。                   ---ok 由於有行間距,因此20過小,最後定爲40px
  (3)爲第三個圖表增長echarts滾動條效果。                       ---ok
  (4)去掉按周排序的「第幾周」。                              ---ok

  七、 讓元素的高度達到必定值的時候出現滾動條:
    在該元素的class中添加以下css屬性便可:

1 .dropdown-menu{overflow: hidden;max-height: 100px;overflow-y: auto;}

  八、 要讓echarts圖表的高度變高到必定值的時候也出現正常的滾動條小果,那麼不能直接在echarts的父div上加滾動條css,而要在父div外面再套一個div,再在這個div上添加滾動條css.

  九、 echarts datazoom數據區縮放控件的藍色拖動條的寬度大一點(但是改變dataZoom控件的handleSize屬性後不起做用,這是個問題)

  十、 ubuntu firefox的cookie文件位置:$HOME/.mozilla/firefox/xxxx.default/目錄下的cookie.sqlite文件。

  十一、 今日備份:快盤。

 [7.20 週一]

  一、 今日任務:餘額記錄重複、遺漏、數值計算錯誤的問題(錯誤可能是由於併發操做沒有加鎖引發的)
    這幾個表:balancehistory(餘額變化記錄),shop(shop_balance),customer_shop_follow(用戶在某店鋪中存的餘額),order(是依據)

  二、 今天裝公司新電腦ubuntu系統裝完之後開機遇到這個問題,且每次開機都會出現:
    System program problem detected
    Do you want to report the problem now?

  三、 昨天的訂單送達時間問題,今天測試又發現沒有問題,仍是要在多家店鋪上面進行測試才行。

  四、 mysql將查詢記錄及結果記錄寫入到外部文件中的方法:
  方法1:
    使用tee命令(登入數據庫的時候要加sudo):
      mysql > tee /home/senguo/log.txt;
      mysql > use mysql;
      mysql > show tables;
      mysql > notee; //關閉記錄功能
  方法2(按照格式寫入excel文件):
    select * from shop
    into outfile '/tmp/test.xls'
    fields terminated by ','
    optionally enclosed by '"'
    lines terminated by '\n';
    注:路徑必須是/tmp/xxx.xxx,不然沒有權限。

  五、 今日任務數據庫分析:
  (1)shop表:
    *shop_balance字段:當前店鋪的餘額
    *available_balance:該店鋪當前的可提現餘額
    *正確的狀況下:同一時刻available_balance <= shop_balanc

  (2)order表:
    *pay_type = Column(TINYINT, default=1)#付款方式:1:貨到付款,2:餘額 3:在線支付
  (3)balancehistory表:
    *balance_type = Column(Integer,default = 1) # 0:表明充值 ,1:餘額消費 2:提現 3:在線支付 4:商家刪除訂單 5:用戶本身取消訂單 6:餘額消費完成 ,可提現額度的變化
    *這個表是從2015-5-3開始有記錄的。
  (4)customer_shop_follow表:
    *shop_balance:該用戶在該店鋪存的餘額

  六、 python3相比python2的輸入函數的變化:
    python3刪除了raw_input,用input代替:
    2.X:guess = int(raw_input('Enter an integer : ')) # 讀取鍵盤輸入的方法
    3.X:guess = int(input('Enter an integer : '))

  七、 mysql用select 1 into outfile '/home/senguo/test/test.xls';命令將查詢結果寫入外部文件出錯:ERROR 1 (HY000): Can't create/write to file '/home/senguo/test/test.xls' (Errcode: 13)
    修改了test文件夾權限:sudo chmod -R 777 /home/senguo/test仍然不行,若是先建立test.xls文件而後修改其權限爲777,則在數據庫中再執行命令:select 1 into outfile '/home/senguo/test/test.xls';又會出現錯誤:ERROR 1086 (HY000): File '/home/senguo/test.xls' already exists
    解決方法:在系統根目錄下有一個'/tmp/'目錄,將上面的sql命令的文件路徑改成'/tmp/test.xls'便可成功執行。

  八、 ubuntu中在命令行下當不知道用什麼程序打開某一個文件的時候,能夠使用:xdg-open file.xxx 的命令自動用默認的對應的程序打開。
    好比:xdg-open test.xls,會自動用excel程序打開當前目錄的test.xls文件。

  九、 mysql改變某一列:alter table senguocc.order change fruits fruits varchar(2000) default NULL;

  十、 店鋪後臺是根據瀏覽器cookie判斷當前店鋪是哪一個店鋪的,若是線上系統和本地系統同時運行,那麼由於cookie的緣由,會致使點擊連接跳到另一個店鋪的問題。因此之後測試的時候仍是不要同時開線上的和線下的比較好。

  十一、 admin-sell-count bug:第三張單種類目銷售統計表,當某種類目中的商品數很是多的時候,會出現圖例(legend)很擁擠的狀況,很是影響美觀,所以最後去掉legend.(ok)

  十二、 admin-sell-count bug:第三張單種類目銷售統計表,當添加新商品並有銷售記錄後,前幾天的銷售記錄的數據會出問題。
    主要緣由:js中object的元素是無序排列的,python的字典也是無序排列的,後臺給js傳參的時候沒有注意到這個問題。

  1三、 python中把一個字典aa中的元素按照鍵名排序並存到一個列表中的方法:
    先得到字典aa的鍵名列表:bb = list(aa.keys())
    而後把列表bb排序:bb.sort()
    而後再以bb的元素爲索引讀取aa中的值:

1 another_list = [ ]
2 for i in range(len(bb)):
3     tmp = { }
4     print(bb[i],":",aa[bb[i]])
5     tmp[bb[i]] = aa[bb[i]]
6     another_list.append(tmp)

   1四、 今日備份:快盤。

 [7.21 週二]

  一、 admin-sell-count a big bug:查詢數據庫的時候用的是商品名稱而不是id致使的不少錯誤,並且還沒考慮到商品的名稱是能夠修改的。通過大規模修改後才解決問題。

    這給了之後一個教訓:全部數據庫查詢必須用不變且惟一的值進行操做(如id),不能想固然用本身以爲對的字段。

  二、 讓echarts在後臺查詢數據的時候就顯示loading畫面的方法:
    將chart和options都定義成全局變量,先初始化chart和option,同時在初始化的function中定義loading函數,不隱藏,而後再發post請求,等到返回成功數據之後再往chart的option裏面添加數據,添加數據後再隱藏loading函數,最後顯示圖表。

  三、 小問題:admin sell count前兩個圖表的排序方式和下面圖表距離太近了,若是圖表過高添加滾動條之後二者就挨在了一塊兒,要增大間距。

  四、 python將整數強制轉換成字符串:str(123)

  五、 python文件操做:
    (1)打開文件:f = open("./test.txt","w+")
    (2)向文件寫入字符串:f.write("") (只能寫入字符串,若是想把列表等用write函數寫入文件,則要先轉化成字符串才行。)
    (3)關閉文件:f.close()

  六、 今日備份:快盤。

  [7.22 週三]

  一、  今日任務:餘額記錄重複、遺漏、數值計算錯誤的問題(錯誤可能是由於併發操做沒有加鎖引發的)
    這幾個表:balancehistory(餘額變化記錄),shop(shop_balance),customer_shop_follow(用戶在某店鋪中存的餘額),order(是依據)

  二、  js實現遮罩層:
    (1)首先在html body塊中寫以下代碼:

1 <body>
2   <input id="btn-check" type="button" value="Showa" onclick="showdiv();"/> 
3   <div id="checkinput_bg"></div>
4   <div id="div-input">  //這個div中的內容爲自定義的內容    
5     <input id="btnclose" type="button" value="Close" onclick="hidediv();"/> 
6   </div>
7 </body> 

    (2)而後在css中寫以下樣式:

1 <style type="text/css">
2   #checkinput_bg{ display: none; position: absolute; top: 0%; left: 0%; width: 100%; height: 100%; background-color: black; z-index:1001;-moz-opacity:0.7;-khtml-opacity: 0.7;opacity:.70; filter: alpha(opacity=70);}
3   #div-input{display: none; position: absolute; top: 25%; left: 22%; width: 53%; height: 49%; padding: 8px; border: 8px solid #E8E9F7; background-color: white; z-index:1002; overflow: auto;}
4 </style>

    (3)最後在js中寫以下代碼添加按鈕的回調函數,控制div的顯示和隱藏:

 1 <script language="javascript" type="text/javascript">
 2   function showdiv() { 
 3     document.getElementById("checkinput_bg").style.display ="block";
 4     document.getElementById("div-input").style.display ="block";
 5   }
 6   function hidediv() {
 7     document.getElementById("checkinput_bg").style.display ='none';
 8     document.getElementById("div-input").style.display ='none';
 9   }
10 </script>

  三、 SQLServer [sikəu 'sə:və]

  四、 mysql改變某一列的結構和屬性:alter table senguocc.order change fruits fruits varchar(2000) default NULL;
    改變某一列的值:update student set name="jyj" where id = 001;

  五、 bug:

 1 File "/home/senguo/KuaiPan/Senguo/gitwork/senguo.cc/admin/handlers/admin.py", line 495, in post
 2 fruit_id = self.session.query(models.Fruit.id).join(models.ChargeType).filter(models.ChargeType.id == int(key)).all()[0][0]
 3 IndexError: list index out of range
 4 
 5 File "/home/senguo/KuaiPan/Senguo/gitwork/senguo.cc/admin/handlers/admin.py", line 608, in post
 6 fruit_id = self.session.query(models.Fruit.id).join(models.ChargeType).filter(models.ChargeType.id == int(key)).all()[0][0]
 7 IndexError: list index out of range
 8 
 9 File "/home/senguo/KuaiPan/Senguo/gitwork/senguo.cc/admin/handlers/admin.py", line 717, in post
10 fruit_id = self.session.query(models.Fruit.id).join(models.ChargeType).filter(models.ChargeType.id == int(key)).all()[0][0]
11 IndexError: list index out of range

    問題所在:沒有對自定義商品進行處理的問題。

  六、 嚴重問題:如今從訂單的fruits字段查詢店鋪的銷售狀況,在數據量較大的時候這樣的方式查詢效率很是低,用戶體驗很是差。
      解決方案:
    (1)想方設法優化目前算法。
    (2)在數據庫中爲每個店鋪新建一張銷售狀況表,該表保存了該店鋪每一筆訂單的每種商品的銷售狀況。從而在查詢銷售狀況的時候能夠直接從這個         表中查詢,大大提升查詢效率。
    (3)在order表中新增長銷售狀況字段,每次在訂單完成後就往該字段中加入這個訂單中每種商品的以下信息,:(商品類目id1:{{商品id1:銷售額,商品id2:           銷售額,...},該類目銷售額},商品類目id2:{{商品id1:銷售額,商品id2:銷售額,...},該類目銷售額},...)  (存爲字符串格式)

  七、 admin-sell-count添加新功能:點擊一個按鈕的時候會出來圖表的全屏瀏覽大圖(須要遮罩層技術)。
    問題:把圖表放在遮罩層中,顯示不出來圖表線條。

  八、 admin-sell-count在店鋪尚未商品的狀況下會出錯。

  九、 第三個表要加上圖例

  十、 第一個表的tooltip要加上每種類目包含的商品名稱
    解決方案:從後臺返回每一種類目包含的商品名稱,把包含的全部商品連成一個字符串,而後把全部類目的數據以字符串數組的形式返回給前臺.前            臺把數據加入到series[1]的data數組中,而後tooltip的formatter函數讀取該數組內容並顯示出來:

 1 options.tooltip.formatter = 
 2   function(params,ticket,callback){
 3     var res = "單類目銷售狀況<br/>" + params[0].name + ":";
 4     res += params[0].data + "<br/>";
 5     res += "包含商品:" + params[1].data;
 6 
 7     setTimeout(function (){
 8       // 僅爲了模擬異步回調
 9       callback(ticket, res);
10     }, 0)
11   };

  十一、 今日備份:快盤,github.  

[7.23 週四]

  一、 今日任務:深度優化銷售統計算法。

  二、 echarts的tooltip的formatter(內容格式器)屬性中能夠加入函數。
    用法舉例:

 1 formatter:function (params,ticket,callback){
 2   var res = "單類目銷售狀況<br/>" + params[0].name + ":";
 3   res += params[0].data;
 4 
 5   setTimeout(function (){
 6     // 僅爲了模擬異步回調
 7     callback(ticket, res);
 8   }, 0)
 9   // return 'loading';
10 }
11 //注:其中每一個params[i]對應一個series中的object

  三、 js取字符串的子串:

1 str = str.substr(start,lenth)

  四、 Echarts legend覆蓋圖表問題:
    echarts的legend選項值過多的時候會覆蓋到下面的圖表,這個問題最後這樣解決:
    在循環中控制給legend的data賦值的個數,當超過這個個數的時候,就給data賦值空字符串便可.

  五、 店鋪後臺銷售統計bug:當店鋪尚未商品的時候前臺和後臺都報錯.
    解決方法:js第一次發post請求,後臺先查詢該店鋪的商品列表是否是爲空,若是爲空就直接返回前臺一個標記,前臺在後面的全部post請求都不必          發了,直接在頁面顯示該店鋪沒有商品便可.

  六、 如今m_goods及相關的幾張表都棄用了,全部商品都存到了fruits表中.以前order表有一個fruits字段和一個mgoods字段,如今mgoods字段也棄用了,     只用fruits字段.

  七、 dbinitdata.py文件中有全部水果的信息.

  八、 問題:echarts放在新的圖層上,新圖層初始化爲hidden,爲一個按鈕綁定點擊事件,點擊的時候顯示這個圖層,但點擊按鈕後發現只能顯示座標軸,     數據並不難顯示出來.
    解決方法:把新圖層div初始化隱藏的方式改成:.invisiable{visibility: hidden;}便可.

  九、 居中問題:
    div居中:
      margin: 0 auto;
    text居中:
      text-align:center;

  十、 銷售統計添加遮罩層顯示大圖功能成功!剩下的就是各類性能優化,以及對於用戶自定義商品的錯誤處理的修正.

  十一、 把除水果和乾果之外的"其餘"商品都當作"其餘"處理.

  十二、 在js中代碼任意處加"debugger;",則能夠進行斷點調試,並且調試的時候變量的值也會自動顯示處理,這個很厲害.

  1三、 chrome瀏覽器模擬手機:打開小手機的圖標,而後在上方的UA欄中輸入MicroMessenger便可.

  1四、 新任務:店鋪後臺的統計項目(前30)
        統計同種類目的銷售額前十名店鋪

  1五、 今日備份:快盤,github.  

[7.24 週五]
  一、 今日任務:
    優化店鋪後臺的銷售統計
    總後臺的銷售統計
  二、 python計算一段程序的執行時間:

1 import time
2 start = time.clock()
3 #這裏是要測試的代碼段
4 ...
5 end = time.clock()
6 print("所用時間爲:",end-start,"")
7 #注:時間單位爲秒,能夠轉化爲毫秒(python的時間戳單位也是毫秒):
8 print(("所用時間爲:%.3fms") % ((end - start)/1000))

  三、 通過斷點測試每一段代碼的執行時間,發現店鋪後臺銷售統計的程序執行時間主要花在了處理訂單中的fruits字段並將fruits字段的數據轉化成單種商品的銷售額這一塊了,數據量稍大的時候這一部分的執行時間佔了總執行時間的90%以上,因此主要在這裏進行性能優化.
    優化方案:
    (1)通過分析發現,消耗時間較多的代碼段主要是在兩個方面消耗時間:
      多重循環和多重循環中的數據庫查詢操做.
      所以考慮將每次循環中相同或重複的數據庫查詢操做在循環開始以前就查好並把結果存在列表裏面,等到要查的時候直接在列表中找,這樣能夠大大優化效率.
      主要的可優化查詢操做有:
      ①select id from charge_type where fruit_id in (select id from fruit where shop_id = self.current_shop.id); --->查詢當前店鋪的全部商品的計價方式的id,並存放在列表中:shop_charge_type_id_list
      ②而後創建一個字典,該字典的鍵表示該店鋪的全部計價方式id,值表示每種計價方式id對應的fruit_id
select fruit_id from charge_type where id in (select id from charge_type where fruit_id in (select id from fruit where shop_id = 4));
        即:select fruit_id from charge_type where id in (select id from charge_type where fruit_id in shop_charge_type_id_list;
      ③再遍歷上一步的字典的每一個fruit_id,根據fruit_id從數據庫中查出對應的全部的fruit_name,並添加到fruit_id的後面,與fruit_id構成一個子字典.
      ④每次在循環中的查詢均可以優化爲判斷每一個order表的fruits字段的計價方式是否在(3)中字典的鍵列表中,若是在則再查對應的fruit_id和fruit_name,這樣能夠初步大大提升效率.
      ⑤對於以前order表的mgoods字段的商品,這樣處理:
        先根據menu表和m_goods表的聯合查詢,查詢當前店鋪全部的自定義商品的id和name,並保存到:shop_mgoods_list表中:
          select m_goods.id,m_goods.name from m_goods,menu where m_goods.menu_id = menu.id and menu.shop_id = self.current_shop.id;
        而後遍歷shop_mgoods_list表,查詢m_charge_type表中全部和shop_mgoods_list表中m_goods_id相同的計價方式id,並存在一個表中:shop_mgoods_ charge_type;
      ⑥最後創建一個字典列表,每一個字典以上述第二步的計價方式id爲鍵,以mgoods_id和mgoods_name組成的列表爲值.
        每次在循環中的查詢均可以優化爲判斷每一個order表的mgoods字段的計價方式在上面字典中對應的mgoods_id和mgoods_name,這樣也能夠初步大大提升效率.

  四、 python中合併兩個字典的方法(假設a,b是兩個字典):
    方法1:c = dict(a,**b)
    方法2:c = a.copy()
       c.update(b)
    從效率上來說方法2的效率更高.

  五、 python獲取字典的鍵列表(假設d爲一個字典):
      key_list = list(d.keys())
    獲取字典的值的列表:
      value_list = list(d.values())
    獲取字典的鍵和值組成的元組的列表:
      item_list = list(d.items())

  六、 python如下代碼並不會改變列表a:

1 a = [1,2,3,4,5]
2 for e in a:
3     e = e+1

    注:但用sqlalchemy對數據庫進行查詢而且作修改的時候,這種方法是能改變原來列表的。這一點要特別注意。

  七、 店鋪後臺銷售統計前兩個表的左邊距過小.

  八、 今日數據備份:快盤,github.

[7.25 週六]

  一、 今日任務:整個森果系統的餘額錯誤對帳
  二、 昨天陳明遇到一個問題:在數據庫中加表之後,推到線上測試的時候由於數據庫的編碼問題致使線上git分支不能用了,解決方法是:
    在admin.py頂部加入:

1 import codecs 
2 codecs.register(lambda name: codecs.lookup(‘utf8’) if name == ‘utf8mb4’ else None)

  三、 上午完成了店鋪後臺的銷售統計的優化,大大提升了查詢速度,將原來數據量大的時候的5秒左右的執行時間優化到了300ms左右,提升了用戶體驗.
    還有一個問題:每一個銷售統計圖的後臺重複代碼略多,能夠考慮進行合併和封裝.

  四、 今日任務數據庫分析:
    (1)shop表:
      *shop_balance字段:當前店鋪的餘額
      *available_balance:該店鋪當前的可提現餘額
      *正確的狀況下:同一時刻available_balance <= shop_balance
      *mysql> select id from shop where shop_code = 'czneau';
      +----+
      | id |
      +----+
      | 4 |
      +----+

      注:「吃在東農」店鋪的數據量比較大,爲了數據統計的方便性,以該店鋪爲例.

    (2)order表:
      *pay_type = Column(TINYINT, default=1)#付款方式:1:貨到付款,2:餘額 3:在線支付
    (3)balancehistory表:
      *balance_type = Column(Integer,default = 1) # 0:表明充值 ,1:餘額消費 2:提現 3:在線支付 4:商家刪除訂單 5:用戶本身取消訂單 6:餘額消費完成 ,可提現額度的變化
      *這個表是從2015-5-3開始有記錄的。
    (4)customer_shop_follow表:
      *shop_balance:該用戶在該店鋪存的餘額

  五、 python中保留小數位數的兩種方法:
      round(1.2222,2),結果爲1.22,類型爲float
      format(1.2222,".2f"),結果爲'1.22',類型爲str

  六、 固然果園:id = 1163;果繽紛:id = 1080

  七、 sqlalchemy的幾種查詢結果的形式總結:
    (1)self.session.query(models.Shop).filter(...).count()
      查詢結果是一個整數,表示知足條件的結果的條數.
    (2)self.session.query(models.Shop).filter(...).all()
      查詢結果是一個list,每個元素都是<class 'dal.models.Shop'>類型的對象.若是查詢結果爲空,則返回一個空的list.
    (3)self.session.query(models.Shop).filter(...).first()
      查詢結果是一個<class 'dal.models.Shop'>類型的對象.若是查詢結果爲空,則返回一個<class 'NoneType'>類型的對象.
    (4)self.session.query(models.Shop.id,models.Shop.shop_name,...).filter(...).all()
      查詢結果是一個list,每個元素都是一個元組,該元組包含了id,shop_name,...這些信息.若是查詢結果爲空,則返回一個空的列表.
    (5)self.session.query(models.Shop.id,models.Shop.shop_name,...).filter(...).first()
      查詢結果是一個元組,類型爲<class 'sqlalchemy.util._collections.result'>,該元組包含了id,shop_name,...這些信息.若是查詢結果爲空,則返回一個None.
    (6)self.session.query(models.Shop).filter(...)
      查詢結果是一個<class 'sqlalchemy.orm.query.Query'>類型的數據,具體內容是一個mysql查詢語句,相似於這樣:

1 SELECT shop.id AS shop_id 
2 FROM shop 
3 WHERE shop.shop_status = %(shop_status_1)s

  八、 數據查詢:

 1     select shop.shop_name,balancehistory.create_time,shop.shop_balance,shop.available_balance,balance_record,balancehistory.balance_value, balancehistory.available_balance,balance_type from balancehistory,shop where shop.id = balancehistory.shop_id and shop.id = 1080 order  by balancehistory.create_time;
 2 
 3     select senguocc.order.id,senguocc.order.shop_id,senguocc.order.create_date,senguocc.order.totalPrice,senguocc.order.pay_type from senguocc.order where shop_id = 235;
 4 
 5     select create_time,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where shop_id = 1163;
 6     select create_time,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where shop_id = 4 order by create_time;
 7     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 0 order by shop_id,create_time;
 8     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 1 order by shop_id,create_time;
 9     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 2 order by shop_id,create_time;
10     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 3 order by shop_id,create_time;
11     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 4 order by shop_id,create_time;
12     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 5 order by shop_id,create_time;
13     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 6 order by shop_id,create_time;
14     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type = 7 order by shop_id,create_time;
15 
16     select create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type in (4,5) order by shop_id,create_time;
17 
18     select senguocc.order.create_date,senguocc.order.pay_type,senguocc.order.num,senguocc.order.totalPrice,senguocc.order.today, senguocc.order.arrival_time from senguocc.order where senguocc.order.shop_id = 4 and senguocc.order.status >= 5 and  date_format(senguocc.order.create_date,"%Y-%m-%d")>"2015-05-02" order by senguocc.order.create_date;
19 
20 
21 
22     select senguocc.order.create_date,senguocc.order.pay_type,senguocc.order.num,senguocc.order.totalPrice,senguocc.order.today, senguocc.order.arrival_time from senguocc.order where senguocc.order.shop_id = 4 and senguocc.order.status >= 5 and 
23  date_format(senguocc.order.create_date,"%Y-%m-%d")>"2015-05-02" order by senguocc.order.create_date;
24 
25     select senguocc.order.create_date,senguocc.order.pay_type,senguocc.order.num,senguocc.order.totalPrice,senguocc.order.today, senguocc.order.arrival_time from senguocc.order where senguocc.order.shop_id = 4 and senguocc.order.status >= 5 and 
26  senguocc.order.pay_type in (2,3) and date_format(senguocc.order.create_date,"%Y-%m-%d")>"2015-05-02" order by senguocc.order.create_date;
27 
28     select create_time,balance_record from balancehistory where balance_type in (1,3) order by create_time;

 

  九、 order表pay_type每一個值表示的意思:
    1:貨到付款,2:餘額 3:在線支付

  十、 店鋪shop_totalPrice分析:
    balance_type的每一個值表示的意思:
    [tee /home/senguo/log.txt](這個語句用於將mysql的輸出結果存儲到一個文本文檔裏,在數據量較大的時候方便分析)
    0:用戶充值;1:餘額消費;2:商家提現;3:在線支付(未完成);4:商家刪除訂單;5:用戶本身取消訂單;6:餘額消費完成;7:在線支付完成
    (1)shop表的shop_balance的值和balancehistory表的該店鋪對應的按時間升序排序的記錄的最後一條記錄的shop_totalPrice的值應該是一致的.
    (2)對於一個特定的shop_id,balancehistory表的該店鋪對應的按時間升序排序的記錄中,當balance_type in [0,1,3]時,應該有:shop_totalPrice = shop_totalPrice' + balance_value,其中shop_totalPrice表示當前記錄中的shop_totalPrice,shop_totalPrice'表示離當前最近的一次的相同的操做記錄的shop_totalPrice.同時available_balance不該該發生變化.
    (3)對於一個特定的shop_id,balancehistory表的該店鋪對應的按時間升序排序的lx記錄中,當balance_type = 2時,應該有:shop_totalPrice = shop_totalPrice' - balance_value同時available_balance = available_balance' - balance_value,其中shop_totalPrice表示當前記錄中的shop_totalPrice,shop_totalPrice'表示離當前最近的一次的操做記錄的shop_totalPrice.available_balance表示當前記錄中的shop_totalPrice,available_balance'表示離當前最近的一次的提現或者可提現額度入帳的操做記錄(balance_type in [2,6,7])的available_balance. 
    (4)對於一個特定的shop_id,balancehistory表的該店鋪對應的按時間升序排序的記錄中,當balance_type in [4,5]時,應該有:shop_totalPrice = shop_totalPrice' - balance_value,其中shop_totalPrice表示當前記錄中的shop_totalPrice,shop_totalPrice'表示離當前最近的一次的balance_type in [0,1,3]的操做記錄的shop_totalPrice.同時available_balance不該該發生變化.

  十一、 店鋪available_balance分析:
    (1)對於一個特定的shop_id,balancehistory表的該店鋪對應的按時間升序排序的記錄中,當balance_type in [6,7]時,available_balance = available_balance' + balance_value,其中available_balance表示當前記錄中的shop_totalPrice,available_balance'表示離當前最近的一次的相同的操做記錄的available_balance.同時shop_totalPrice不該該發生變化.
    (2)對於一個特定的shop_id,balancehistory表的該店鋪對應的按時間升序排序的記錄中,當balance_type = 2時,應該有:shop_totalPrice = shop_totalPrice' - balance_value同時available_balance = available_balance' - balance_value,其中shop_totalPrice表示當前記錄中的shop_totalPrice,shop_totalPrice'表示離當前最近的一次的操做記錄的shop_totalPrice.available_balance表示當前記錄中的shop_totalPrice,available_balance'表示離當前最近的一次的提現或者可提現額度入帳的操做記錄(balance_type in [2,6,7])的available_balance.

  十二、 balance_type分析:
    (1)能致使shop_totalPrice增大的balance_type有:[0,1,3];能致使shop_totalPrice減少的balance_type有:[2,4,5];shop_totalPrice不變的balance_type有:[6,7]
    (2)能致使available_balance增大的balance_type有:[6,7];能致使available_balance減少的balance_type有:[2];available_balance不變的balance_type有:[0,1,3,4,5].

  1三、 總額分析:
    (1)對於某一個店鋪的balancehistory,在按照時間升序排列的記錄中,全部balance_type in [6,7]的記錄的balance_value加起來並減去全部balance_type=2的記錄的balance_value,結果應該等於店鋪當前最新的available_balance.
    (2)同一時刻應該有available_balance <= shop_balanc
    (3)由於有些訂單由於併發等緣由並無記錄到balancehistory表中,因此對帳的時候要以order表爲依據.

  1四、 發現的問題整理:
    (1)shop_id = 1163
+---------------------+--------------+------------------------------------------------+---------------+-----------------+-------------------+
| create_time | balance_type | balance_record | balance_value | shop_totalPrice | available_balance |
+---------------------+--------------+------------------------------------------------+---------------+-----------------+-------------------+
| 2015-06-05 16:31:45 | 7 | 可提現額度入帳:訂單1163000001完成 | 2.5 | 2.5 | 2.5 |
| 2015-06-05 16:32:31 | 3 | 在線支付(支付寶):訂單1163000002 | 6.5 | 9 | 0 |
    

    (2)shop_id = 1163
| 2015-06-07 13:49:57 | 3 | 在線支付(微信):訂單1163000132 | 6.5 | 1051.6 | 0 |
| 2015-06-07 14:00:51 | 7 | 可提現額度入帳:訂單1163000118完成 | 9 | 1051.6 | 11.5 |


    (3)shop_id = 1163
| 2015-06-07 14:05:24 | 7 | 可提現額度入帳:訂單1163000084完成 | 7.5 | 1051.6 | 993.1 |
| 2015-06-07 14:11:53 | 3 | 在線支付(支付寶):訂單1163000134 | 14 | 1065.6 | 0 |


    (4)
| 2015-06-07 14:05:24 | 7 | 可提現額度入帳:訂單1163000084完成 | 7.5 | 1051.6 | 993.1 |
| 2015-06-07 14:11:53 | 3 | 在線支付(支付寶):訂單1163000134 | 14 | 1065.6 | 0 |


    (5)
| 2015-06-07 18:55:21 | 3 | 在線支付(支付寶):訂單1163000158 | 14.3 | 1333.5 | 0 |
| 2015-06-07 19:04:28 | 7 | 可提現額度入帳:訂單1163000153完成 | 20.3 | 1333.5 | 1013.4 |


    (6)
| 2015-06-08 09:45:36 | 3 | 在線支付(支付寶):訂單1163000255 | 2.5 | 2254.7 | 0 |
| 2015-06-08 09:46:04 | 2 | 提現:管理員 歐先森•固然果園 | 1350 | 904.7 | 29.9 |
| 2015-06-08 09:46:57 | 3 | 在線支付(微信):訂單1163000259 | 16 | 920.7 | 0 |


    (7)
| 2015-06-08 19:31:59 | 3 | 在線支付(微信):訂單1163000451 | 6 | 2594.6 | 0 |
| 2015-06-08 19:34:01 | 7 | 可提現額度入帳:訂單1163000331完成 | 3 | 2594.6 | 32.9 |


    (8)
| 2015-06-09 10:58:55 | 3 | 在線支付(支付寶):訂單1163000597 | 13.8 | 3966.4 | 0 |
| 2015-06-09 10:59:23 | 2 | 提現:管理員 歐先森•固然果園 | 2600 | 1366.4 | 64.9 |
| 2015-06-09 11:03:34 | 3 | 在線支付(微信):訂單1163000599 lx | 15 | 1381.4 | 0 |


    (9)
| 2015-06-09 22:08:48 | 3 | 在線支付(微信):訂單1163000719 | 5.8 | 2531.1 | 0 |
| 2015-06-09 22:32:53 | 2 | 提現:管理員 歐先森•固然果園 | 2400 | 131.1 | 64.1 |
| 2015-06-09 22:36:34 | 3 | 在線支付(支付寶):訂單1163000720 | 13.3 | 144.4 | 0 |
    注:以上問題是由於在生成記錄的時候根本就沒有記錄當前操做不會改變的項的值,只要保證離當前最近的一次的相同的操做的該項的值正確就能夠.這一點不會形成數據錯誤.

  1五、 訂單號組成:前若干位是店鋪id,後6位是該店鋪的訂單的累計個數.

  1六、 在如下c語言代碼段中只能修改或增長或刪除一個字符,使得輸出結果是20個'-',給出三種方法(今天陳明不知道從哪找的一個題)
    代碼段:

1 #include <stdio.h>
2 int main()
3 {
4     int n = 20;
5     int i;
6     for(i = 0; i < n;i--){
7         printf("-");    
8     }
9 }    
 1 //方法1:
 2 #include <stdio.h>
 3 int main()
 4 {
 5     int n = 20;
 6     int i;
 7     for(i = 0; i + n;i--){
 8         printf("-");    
 9     }
10 }
11 
12 //方法2:
13 #include <stdio.h>
14 int main()
15 {
16     int n = 20;
17     int i;
18     for(i = 0; i < n;n--){
19         printf("-");    
20     }
21 }
22 
23 //方法3:
24 #include <stdio.h>
25 int main()
26 {
27     int n = 20;
28     int i;
29     for(i = 0; -i < n;i--){
30         printf("-");    
31     }
32 }            

  1七、 sqlalchemy查詢中,filter和filter_by的區別:
    (1)filter:
      self.session.query(models.Shop.shop_name).filter(models.Shop.id == 888).all()
    (2)filter_by:
      self.session.query(models.Shop.shop_name).filter(id = 888).all()
    結論:仍是filter_by的寫法比較簡單,之後若是隻判斷相等關係都用filter_by.若是判斷其餘的如不等關係、in關係等,仍是要用filter.

  1八、 sqlalchemy若是某一個表類的某一個字段和另一張表有relationship關係,那麼能夠直接引用該relationship字段的子字段,好比在order表中有以下shop字段:

1 class Order(MapBase, _CommonApi):
2       ...
3       shop = relationship("Shop", uselist=False,join_depth=1)
4       ...

    那麼能夠直接這樣寫:

1 shop_order = self.session.query(models.Order).filter_by(shop_id = 4).first()
2 print(shop_order.shop.shop_name)

    輸出結果是id = 4的店鋪的名稱.

   1九、 今日數據:快盤,github.

[7.27 週一]

  一、 今日任務:餘額錯誤對帳
  二、 提取字符串中第若干位到倒數第三位之間的數字子串:

1 str0 = "可提現額度入帳:訂單1234002379121完成"
2 i = -1
3 while i < len(str0):
4 i += 1
5 if str0[i].isdigit():
6 break
7 print(str0[-(len(str0) - i) : -2])

    輸出結果:1234002379121

  三、 查找一下balancehistory表中最先是從什麼開始將shop_totalPrice和available_balance分離的(即在balance_record字段中balance_type in (6,7)第一次出現的記錄).
    select create_time,balance_type,balance_record,balance_value,shop_totalPrice,available_balance from balancehistory where balance_type in (6,7) order by create_time;
    查詢結果第一條爲:
+---------------------+--------------+------------------------------------------------+---------------+-----------------+-------------------+
| create_time | balance_type | balance_record | balance_value | shop_totalPrice | available_balance |
+---------------------+--------------+------------------------------------------------+---------------+-----------------+-------------------+
| 2015-05-09 11:35:00 | 6 | 可提現額度入帳:訂單607000133完成 | 27 | 173 | 109 |

    查詢全部用餘額支付或在線支付方式的訂單的信息:
select senguocc.order.create_date,senguocc.order.pay_type,senguocc.order.num,senguocc.order.totalPrice,senguocc.order.today,senguocc.order.arrival_time from senguocc.order where senguocc.order.status >= 5 and senguocc.order.pay_type in (2,3) and date_format(senguocc.order.create_date,"%Y-%m-%d")>"2015-05-02" order by senguocc.order.create_date;
    從查詢結果中查訂單號爲的訂單信息是:
+---------------------+----------+------------+------------+-------+--------------+
| create_date | pay_type | num | totalPrice | today | arrival_time |
+---------------------+----------+------------+------------+-------+--------------+
| 2015-05-08 12:06:55 | 2 | 607000133 | 27 | 1 | 11:35 |

  四、 查錯思路:
    *範圍一:全部餘額支付和在線支付(還未支付完成)的訂單
    (1)先查詢balancehistory表全部balance_type in (1,3)的balance_record字段,按時間升序排列,分離balance_record字段中的訂單號,並存到一個list balance_type_1_3中.
    (2)而後查詢order表中全部pay_type in (2,3)而且status >= 5的shop_id和num字段,按時間升序排列,將每一組shop_id和num字段組成一個子列表,並存到一個list pay_type_2_3中.
    (3)循環遍歷pay_type_2_3,每次循環查找pay_type_2_3的元素的第二項(訂單編號)是否在表balance_type_1_3中,若是不在,輸出該元素的第一項和第二項.


    *範圍二:全部餘額支付和在線支付(支付完成)的訂單
    (1)先查詢balancehistory表全部balance_type in (6,7)的balance_record字段,按時間升序排列,分離balance_record字段中的訂單號,並存到一個列表listbalance_type_6_7中. 
    (2)而後查詢order表中全部pay_type in (2,3)而且status >= 5的shop_id和num字段,按時間升序排列,將每一組shop_id和num字段組成一個子列表,並存到一個list pay_type_2_3中.
    (3)循環遍歷pay_type_2_3,每次循環查找pay_type_2_3的元素的第二項(訂單編號)是否在表list balance_type_6_7中,若是不在,輸出該元素的第一項和第二項.

  五、 全部訂單表中有的餘額和在線支付(未完成)記錄要插入到balancehistory表中,時間用訂單的create_date;
    全部訂單表中有的餘額和在線支付完成的記錄要插到balancehistory表中,時間用訂單的arrival_day和arrival_time合起來的時間.
    注:插入時候balancehistory的id仍是按照自動增加的方式,依次排列.

  六、 balancehistory在5.14和5.15兩天有八條balance_record異常的記錄,要經過時間查詢訂單號,而後修正過來.

    select create_time,id,customer_id,balance_record,balance_value from balancehistory where balance_type in (1,3) order by create_time;
    select create_date,num,customer_id,shop_id,arrival_day,arrival_time,totalPrice from senguocc.order where date_format(create_date,"%Y-%m-%d %H") like "2015-05-15 12" and customer_id = 33111;
+---------------------+-------+-------------+--------------------------------------------+---------------+
| create_time | id | customer_id | balance_record | balance_value |
+---------------------+-------+-------------+--------------------------------------------+---------------+
| 2015-05-14 23:56:44 | 698 | 1 | 在線支付(微信):用戶 黃鐵森 | 0.01 |
| 2015-05-15 00:29:07 | 699 | 16435 | 在線支付(微信):用戶 託物言志 | 14 |
| 2015-05-15 01:25:44 | 700 | 1854 | 在線支付(微信):用戶 Woody | 4.46 |
| 2015-05-15 01:28:44 | 701 | 1 | 在線支付(微信):用戶 黃鐵森 | 0.01 |
| 2015-05-15 09:01:27 | 719 | 29452 | 在線支付(微信):用戶 美然 | 8.98 |
| 2015-05-15 12:29:18 | 728 | 32843 | 在線支付(微信):用戶 96line7 | 13 |
| 2015-05-15 12:38:14 | 729 | 10788 | 在線支付(微信):用戶 馮藝 | 22.5 |
| 2015-05-15 12:43:06 | 731 | 33111 | 在線支付(微信):用戶 張淑娜。 | 10 |

+---------------------+-----------+-------------+---------+-------------+--------------+------------+
| create_date | num | customer_id | shop_id | arrival_day | arrival_time | totalPrice |
+---------------------+-----------+-------------+---------+-------------+--------------+------------+
| 2015-05-14 23:56:23 | 197000176 | 1 | 197 | NULL | NULL | 0.01 |
| 2015-05-15 00:27:36 | 615000311 | 16435 | 615 | 2015-05-15 | 18:59 | 14 |
| 2015-05-15 01:24:33 | 271000022 | 1854 | 271 | 2015-05-15 | 11:39 | 4.46 |
| 2015-05-15 01:28:24 | 197000177 | 1 | 197 | NULL | NULL | 0.01 |
| 2015-05-15 09:00:29 | 624001065 | 29452 | 624 | 2015-05-16 | 22:19 | 8.98 |
| 2015-05-15 12:29:06 | 848000584 | 32843 | 848 | 2015-05-15 | 19:01 | 13 |
| 2015-05-15 12:37:51 | 624001076 | 10788 | 624 | 2015-05-16 | 22:20 | 22.5 |
| 2015-05-15 12:42:41 | 848000585 | 33111 | 848 | 2015-05-15 | 19:02 | 10 |
+---------------------+-----------+-------------+---------+-------------+--------------+------------+

    select num from senguocc.order where date_format(create_date,"%Y-%m-%d %H-%M-%S") like "2015-05-14 12:36:00";
    問題:由於訂單的create_date和balancehistory的create_time字段存在幾秒到幾分鐘的時間延遲,因此經過時間反查訂單號的方法行不通.
    解決方案:手動修改這八條記錄.

  七、 Mysql中如何建立一個表讓id自動增加?

1 CREATE TABLE users (
2     id int(5) NOT null auto_increment,
3     name varchar(20)NOT null,
4     PRIMARY KEY (`id`)
5 )

    舉例:

1 create table test_autoid (id int(11) not null primary key auto_increment,name char(5) not null);
2 insert into test_autoid(name) values('jyj');
3 ...(省略了八條插入)
4 select * from test_autoid;

+----+------+
| id | name |
+----+------+
| 1 | jyj |
| 2 | aa |
| 3 | bb |
| 4 | cc |
| 5 | d |
| 6 | eee |
| 7 | ff |
| 8 | gg |
| 9 | hh |
+----+------+

1 delete from test_autoid where id = 3;
2 select * from test_autoid;

+----+------+
| id | name |
+----+------+
| 1 | jyj |
| 2 | aa |
| 4 | cc |
| 5 | d |
| 6 | eee |
| 7 | ff |
| 8 | gg |
| 9 | hh |
+----+------+

1 insert into test_autoid(name) values('new');
2 select * from test_autoid;

+----+------+
| id | name |
+----+------+
| 1 | jyj |
| 2 | aa |
| 4 | cc |
| 5 | d |
| 6 | eee |
| 7 | ff |
| 8 | gg |
| 9 | hh |
| 10 | new |
+----+------+

  八、 改錯步驟:
    mysql> select balance_record from balancehistory where balance_type = 3 and (balance_record not like '在線支付(微信):訂單%' and balance_record not like '在線支付(支付寶):訂單%');
+--------------------------------------------+
| balance_record |
+--------------------------------------------+
| 在線支付(微信):用戶 黃鐵森 |
| 在線支付(微信):用戶 託物言志 |
| 在線支付(微信):用戶 Woody |
| 在線支付(微信):用戶 黃鐵森 |
| 在線支付(微信):用戶 美然 |
| 在線支付(微信):用戶 96line7 |
| 在線支付(微信):用戶 馮藝 |
| 在線支付(微信):用戶 張淑娜。 |
+--------------------------------------------+
    select id,create_time,shop_id,balance_type,balance_record,balance_value,customer_id,customer_totalPrice,shop_totalPrice,available_balance, is_cancel from balancehistory where shop_id = 197 order by create_time;

    (1)先手動將balancehistory的八條異常記錄修正:在線支付(微信):訂單% 在線支付(支付寶):訂單

1 update balancehistory set balance_record="在線支付(微信):訂單197000176" where id = 698;
2 update balancehistory set balance_record="在線支付(微信):訂單615000311" where id = 699;
3 update balancehistory set balance_record="在線支付(微信):訂單271000022" where id = 700;
4 update balancehistory set balance_record="在線支付(微信):訂單197000177" where id = 701; 
5 update balancehistory set balance_record="在線支付(微信):訂單624001065" where id = 719;
6 update balancehistory set balance_record="在線支付(微信):訂單848000584" where id = 728;
7 update balancehistory set balance_record="在線支付(微信):訂單624001076" where id = 729;
8 update balancehistory set balance_record="在線支付(微信):訂單848000585" where id = 731;

    臨時記錄:'197000176','615000311','271000022','197000177','624001065','848000584','624001076','848000585'
698,699,700,701,719,728,729,731

    (2)刪除shop_id = 0的記錄。
      delete from balancehistory where shop_id = 0 or id = 19088;
    (3)查詢balancehistory表全部balance_type in (1,3)的balance_record字段,按時間升序排列,分離balance_record字段中的訂單號,並存到一個list balance_type_1_3中:

1 balance_type_1_3 = []
2 query_list = self.session.query(models.BalanceHistory.create_time,models.BalanceHistory.balance_record).filter(models.BalanceHistory.balance_type.in_([1,3])).all()
3 for item in query_list:
4     for i in range(len(item[1])):
5     if item[1][i].isdigit():
6         break
7     balance_type_1_3.append(item[1][i : len(item[1])])    

    (4)查詢order表中全部pay_type in (2,3)而且status >= 5的shop_id和num字段,按時間升序排列,將每一組shop_id和num字段組成一個子列表,並存到一個list pay_type_2_3中;

    *注意事項:由於balancehistory中每一條記錄與其餘記錄的店鋪餘額和可提現餘額都是相互關聯的,因此爲了不混亂,首先只需把缺乏的不包括這兩項的記錄插到表中,而後再依據其餘信息依次推出這兩項的值。


  九、 python的format的用法:

1 >>>"i am {0} years old,i am now in {1}".format(22,'wuhan')
2 'i am 22 years old,i am now in wuhan'

  十、 今日數據:快盤,github.

[7.28 週二]

  一、 今日任務:餘額錯誤對帳
  二、 查詢每一個店鋪的當前shop表中的shop_balance,available_balance兩個值是否與balancehistory表中該店鋪最後一條記錄的二者的值是否相吻合.

1 select id,shop_id,create_time,shop_totalPrice,available_balance from balancehistory where balance_type in(0,1,2,3,4,5) order by shop_id,create_time desc;
2 select shop_id,shop_totalPrice,available_balance from balancehistory where balance_type in(2,6,7) group by shop_id order by create_time desc limit 0,1;

    注:由於分組查詢再取limit會出現錯誤,即分組後查詢後再取每組的第一個值的問題沒有解決,因此分組查詢後在python中進行處理取最新一條記錄的值。


  三、 mysql取分組後每組最後一條數據的一個方法:

 1 create table test_group(id0 int(5) primary key,id int,name char(5));
 2 ...(幾個insert語句)
 3 select * from test_group;
 4 +-----+------+------+
 5 | id0 | id | name |
 6 +-----+------+------+
 7 | 1 | 100 | aa |
 8 | 2 | 100 | bb |
 9 | 3 | 100 | cc |
10 | 4 | 101 | dd |
11 | 5 | 101 | ee |
12 | 6 | 102 | ff |
13 | 7 | 102 | gg |
14 | 8 | 102 | hh |
15 | 9 | 102 | ii |
16 | 10 | 103 | jj |
17 +-----+------+------+
18 select id0,name from test_group X where id0 in (select max(id0) from test_group Y group by (id));
19 +-----+------+
20 | id0 | name |
21 +-----+------+
22 | 3 | cc |
23 | 5 | ee |
24 | 9 | ii |
25 | 10 | jj |
26 +-----+------+

  四、 mysql子查詢不支持limit問題解決
    This version of MySQL doesn’t yet support ‘LIMIT & IN/ALL/ANY/SOME 錯誤解決
    在一個Mysql表達式中使用嵌套查詢,出現了這個錯誤。緣由是內層select語句帶有limit子句。
    在網上查了下,有文章指出:
    好比這樣的語句是不能正確執行的。

1 select * from table where id in (select id from table limit 12);

    可是,只要你再加一層就行。如:

1 select * from table where id in (select t.id from (select * from table limit 12)as t)

    這樣就能夠繞開limit子查詢的問題。
    問題解決。
    後來我發現,上述是解決問題的一個方法,其實還有一個更好的作法,就是把限制條件放到from而非where子句中,就沒必要出現嵌套再嵌套。
如上例,能夠改成:

1 select * from (select id from table limit 12) as foo;

    注意:其實as foo特別重要,若是不寫成from () as xxx的形式,即不給from後的select語句構成表名,那麼最後系統仍會報錯。

  五、 balancehistory表中balance_type in (4,5)的記錄表示的是商家刪除訂單或者用戶取消訂單的記錄,但這樣的記錄的訂單號在order表中對應的status都爲0,因此若是order表中有遺漏的status=0的記錄沒有插入到balancehistory表中,那麼插入的時候都按照balance_type=5進行插入。

    #用戶在線支付成功的訂單不能取消也不能刪除,但餘額支付的訂單能夠。
    #餘額支付的訂單不會有「未付款」的狀態,由於在提交訂單的同時會進行餘額支付操做,而在線支付提交訂單並不會同時支付,而是還要進入支付頁面進行支付。
    #通過檢測,發現不存在balancehistory中店鋪之外的店鋪沒有插入相關記錄的狀況,所以只考慮balancehistory表中的店鋪的錯漏,因此shop_list_query2能夠先不考慮。
    #order表中online_type字段表示在線支付的類型('wx'或'alipay')
    #設定一個change_shop_id列表,把balancehistory表中修改過的店鋪的id都存進去.

1 select create_date,pay_type,totalPrice from senguocc.order where shop_id = 1080 and num = "1080000332";
2 select num,pay_type,status,totalPrice from senguocc.order where shop_id = 1080 and customer_id = 48338;
3 select create_time,shop_id,balance_type,balance_record,balance_ value, shop_totalPrice,available_balance from balancehistory where shop_id = 1080 order by create_time;

  六、 sqlalchemy修改數據庫中某一個表的某些字段的值的方法:

query = self.session.query(models.Order).filter_by(num = "1203000000").first()
query.pay_type = 22
self.session.commit()

  七、 sqlalchemy向表中添加記錄的方法:

1 balance_history = models.BalanceHistory(customer_id = insert_list[i][0],\
2 shop_id = insert_list[i][1] ,name = insert_list[i][2],balance_value = insert_list[i][3] ,\
3 balance_record = insert_list[i][4],create_time = insert_list[i][5],balance_type = 1)
4 self.session.add(balance_history)
5 self.session.commit()

  八、 sqlalchemy上鎖方法:

1 query = self.session.query(models.Order).filter_by(num = "1203000000").with_lockmode("update").first()

  九、 元組中的元素不能進行自加操做,只能先把元組轉化爲字符串(用list方法),而後才能執行自加操做

  十、 今日數據:快盤,github.

[7.30 週四]
  一、 今日任務:餘額錯誤對帳

1 select create_time,shop_id,balance_type,balance_record,balance_ value, shop_totalPrice,available_balance from balancehistory order by shop_id,create_time;
2 select shop_id,count(*) from balancehistory where count(*) < (select count(*) from senguocc.order where senguocc.order.shop_id = balancehistory.shop_id and senguocc.order.pay_type = 3) group 
3 by shop_id;
4 select shop_id,count(*) from balancehistory where balance_type = 3 group by shop_id;

  二、 異常數據:

 1 totalprice: 39 10.4 0
 2 totalprice: 259 66.5 0
 3 available_balance: 271 0.0 8.92
 4 totalprice: 287 16.5 0
 5 totalprice: 444 70.0 0
 6 totalprice: 563 26.4 0
 7 totalprice: 838 1.0 0
 8 totalprice: 1037 10.0 0
 9 available_balance: 1037 10.0 0
10 totalprice: 1057 1.0 0
11 available_balance: 1057 0.01 0
12 totalprice: 1108 2.0 0
13 totalprice: 1115 11.0 0
14 totalprice: 1141 3.0 0
15 totalprice: 1230 4.0 0
16 totalprice: 1284 1.0 0
17 totalprice: 1317 0.01 0
18 totalprice: 1340 1.01 0
19 totalprice: 1473 38.0 0

  三、 零散後臺打印數據記錄:

 1 !!@@@11111111111111 197
 2 @@@@ 7
 3 4
 4 ['197000154', '197000155', '197000156']
 5 !!@@@11111111111111 661
 6 @@@@ 2
 7 0
 8 ['661000036', '661000037']
 9 !!@@@11111111111111 848
10 @@@@ 2
11 1
12 ['848000285']
1 [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 69, 69, 69, 69, 69, 69, 69, 69, 197, 197, 197, 197, 197, 197, 235, 272, 289, 289, 289, 488, 488, 549, 549, 607, 607, 607, 
2 607, 607, 607, 607, 615, 624, 624, 624, 624, 624, 624, 624, 624, 661, 661, 661, 661, 661, 848, 866, 866, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 1037, 1057, 
3 1080, 1080, 1080, 1080, 1080, 1080, 1080, 1194]

  四、 零散mysql查詢記錄:

 1 mysql> select count(*) from balancehistory order by shop_id,create_time;
 2 +----------+
 3 | count(*) |
 4 +----------+
 5 | 18723 |
 6 +----------+
 7 1 row in set (0.01 sec)
 8 
 9 mysql> select shop_balance,available_balance from shop where id = 4;
10 +--------------+-------------------+
11 | shop_balance | available_balance |
12 +--------------+-------------------+
13 | 129.42 | 37.1 |
14 +--------------+-------------------+
15 1 row in set (0.00 sec)
16 
17 mysql> select count(*) from balancehistory where shop_id = 4;
18 +----------+
19 | count(*) |
20 +----------+
21 | 1388 |
22 +----------+
 1 mysql> select count(*) from balancehistory order by shop_id,create_time;
 2 +----------+
 3 | count(*) |
 4 +----------+
 5 | 18723 |
 6 +----------+
 7 1 row in set (0.01 sec)
 8 
 9 mysql> select shop_balance,available_balance from shop where id = 4;
10 +--------------+-------------------+
11 | shop_balance | available_balance |
12 +--------------+-------------------+
13 | 129.42 | 37.1 |
14 +--------------+-------------------+
15 1 row in set (0.00 sec)
16 
17 mysql> select count(*) from balancehistory where shop_id = 4;
18 +----------+
19 | count(*) |
20 +----------+
21 | 1388 |
22 +----------+
 1 select shop_balance from customer_shop_follow where shop_id = 197 and customer_id = (select customer_id from senguocc.order where num = '197000154') ;
 2 select shop_balance from customer_shop_follow where shop_id = 197 and customer_id = (select customer_id from senguocc.order where num = '197000155') ;
 3 select shop_balance from customer_shop_follow where shop_id = 197 and customer_id = (select customer_id from senguocc.order where num = '197000156') ;
 4 select shop_balance from customer_shop_follow where shop_id = 661 and customer_id = (select customer_id from senguocc.order where num = '661000036') ;
 5 select shop_balance from customer_shop_follow where shop_id = 661 and customer_id = (select customer_id from senguocc.order where num = '661000037') ;
 6 select shop_balance from customer_shop_follow where shop_id = 848 and customer_id = (select customer_id from senguocc.order where num = '848000285') ;
 7 
 8 select count(*) from balancehistory order by shop_id,create_time;
 9 
10 select id,create_time,shop_id,balance_type,balance_record,balance_value,shop_totalPrice,available_balance,is_cancel from balancehistory order by shop_id,create_time;

  五、 order表中的del_reason字段能夠判斷訂單刪除或取消的緣由:若del_reason字段爲'timeout'則表示是在線支付未付款(status = -1)超時形成的訂單取消;若del_reason爲空,則表示是用戶取消的;若del_reason非空且不爲'timeout',則表示是商家刪除的.此外,由於現有訂單表中沒有記錄訂單的取消或刪除時間,因此默認設定建立時間後的15分鐘爲刪除時間. 

  六、 *篩選出shop_id錯誤的記錄並修正.

    *將balancehistory表中的全部店鋪id查出來存放在列表shop_list_query1中
    *將系統中的全部status > -1的訂單的數量不爲0店鋪的id查詢出來存在一個列表shop_list_query2中
    *而後從列表shop_list_query2中除去shop_list_query1中的id
    *設定一個change_shop_id列表,把balancehistory表中修改過的店鋪的id都存進去.
    *遍歷shop_id_list1每個shop的id
    *查詢店鋪號在balancehistory中對應的shop_totalprice最新記錄
    *查詢店鋪號在balancehistory中對應的available_balance最新記錄
    *查詢店鋪號在shop表中對應的shop_totalprice和available_balance字段值
    *檢查每個店鋪的店鋪餘額是否與balancehistory中的一致
    *判斷shop表和balancehistory表兩表中的shop_totalPrice和available_balance兩個字段是否分別一致
    *查詢balancehistory表中的全部餘額支付(balance_type = 1)的記錄的訂單號並存到列表balance_type_1中
    *查詢order表中的全部餘額支付(pay_type = 2)的記錄的訂單號並存到列表pay_type_2中
    *判斷pay_type_2的長度是否大於balance_type_1,若大於,則說明order表中確定有餘額支付的訂單記錄沒有插入到balancehistory表中,這時就要把相關記錄插入到balancehistory表中.
  七、 python獲取過15分鐘之後的時間:

1 >>>import datetime
2 >>> now = datetime.datetime(2015,12,31,23,59,50)
3 >>> now
4 datetime.datetime(2015, 12, 31, 23, 59, 50)
5 >>> now = now + datetime.timedelta(minutes=15)
6 >>> now
7 datetime.datetime(2016, 1, 1, 0, 14, 50)

  八、 python列表去重的二種方法:
    第一種

1 def delRepeat(liebiao):
2     for x in liebiao:
3         while liebiao.count(x)>1:
4         del liebiao[liebiao.index(x)]
5     return liebiao    

    第二種 沒法保持原有順序

1 liebiao=set(liebiao)

  九、 sqlalchemy存儲過程

  十、 如今已經把order表中漏的記錄都插到balancehistory表中了,期間遇到的最大的問題就是5月10號以前由於沒有開通在線支付,只有餘額支付才能在balancehistory表中產生記錄,並且當時可能也尚未available_balance字段,換句話說,在5月10號以前這個時間段中,只要用戶往一個店鋪中充了餘額,那麼無論這個餘額用仍是沒有用,店鋪管理員都是能夠提現的。折騰了這麼幾天發現出錯的地方也絕大部分都集中在這個時間段,大多都是餘額支付或者餘額支付的訂單完成或者餘額支付的訂單刪除的記錄沒有插入到表中,只有一少部分多是由於線程競爭或者併發操做等其餘緣由致使的錯誤。牽一髮而動全身,下一步就是修改balancehistory表中凡是出現了上述問題的全部shop_totalPrice和available_balance字段的值。  
    修改的大體思路以下:按照時間升序和按照店鋪id分組遍歷整張balancehistory表,當前記錄的shop_totalPrice和available_balance字段的值能夠根據當前的balance_value,balance_type以及上一條記錄的shop_totalPrice和available_balance字段的值推算出來。
    鑑於有這麼個特殊狀況:當balance_type not in [2,6,7]時,available_balance都爲0,因此當要推算當前記錄的available_balance字段的值時,可能上一條記錄中並無available_balance的正確值(上一條的balance_type not in [2,6,7],故available_balance爲無效的0),因此還要從當前位置開始往前遍歷,直到遍歷到第一條balance_type in [2,6,7]的記錄,並讀取其available_balance值,而後加上當前記錄的balance_value值便可得當前記錄的available_balance值。 
    實現方式上,一開始想的是利用mysql的存儲過程遍歷整張表,而後按照上面的方法修改,可是後來考慮了一下,存儲過程仍是有點複雜了,還不如先循環遍歷表中全部的店鋪id(或者只遍歷進行了修改的店鋪的id),而後在每一次循環中按照時間升序,把當前店鋪對應的每條記錄的:id,create_time,balance_type,balance_value ,shop_totalPrice,available_balance這些字段查詢出來而且存放到一個二維的列表中。而後遍歷這個列表,從第二項開始,第i項的shop_totalPrice和available_balance元素的值均可以用上面的算法計算出來而後存到原處。等遍歷完這個列表之後,就能夠根據id項經過sqlalchemy修改相應的字段了.
  十一、 今日數據:快盤,github.


[7.31 週五]

  一、 今日任務:餘額錯誤對帳
  二、 數據臨時記錄:

 1 //(改錯前):
 2 mysql> select id,shop_name,shop_balance,available_balance from shop where shop_balance < available_balance;
 3 +------+-----------+--------------+-------------------+
 4 | id | shop_name | shop_balance | available_balance |
 5 +------+-----------+--------------+-------------------+
 6 | 1080 | 果繽紛 | 125 | 206.5 |
 7 +------+-----------+--------------+-------------------+
 8 
 9 mysql> select shop_balance,available_balance from shop where id = 4;
10 +--------------+-------------------+
11 | shop_balance | available_balance |
12 +--------------+-------------------+
13 | 155.42 | 58.1 |
14 +--------------+-------------------+
15 
16 
17 //(改錯後):
18 mysql> select shop_balance,available_balance from shop where id = 4;
19 +--------------+-------------------+
20 | shop_balance | available_balance |
21 +--------------+-------------------+
22 | 155.42 | 311.6 |
23 +--------------+-------------------+
24 
25 mysql> select shop_balance from customer_shop_follow where shop_id = 1080 and customer_id = 2105;
26 +--------------+
27 | shop_balance |
28 +--------------+
29 | -75 |
30 +--------------+
31 1 row in set (0.00 sec)
32 
33 mysql> select sum(balance_value) from balancehistory where balance_type = 0 and customer_id = 2105 and shop_id = 1080;
34 +--------------------+
35 | sum(balance_value) |
36 +--------------------+
37 | 22 |
38 +--------------------+
39 1 row in set (0.00 sec)
40 
41 mysql> select sum(balance_value) from balancehistory where balance_type = 1 and customer_id = 2105 and shop_id = 1080;
42 +--------------------+
43 | sum(balance_value) |
44 +--------------------+
45 | 98.29999947547913 |
46 +--------------------+
47 1 row in set (0.00 sec)
48 
49 mysql> select sum(balance_value) from balancehistory where balance_type in (6,7) and customer_id = 2105 and shop_id = 1080;
50 +--------------------+
51 | sum(balance_value) |
52 +--------------------+
53 | 61.19999957084656 |
54 +--------------------+
55 1 row in set (0.00 sec)
56 
57 mysql> select sum(balance_value) from balancehistory where balance_type = 0 and customer_id = 2105 and shop_id = 1080;
58 +--------------------+
59 | sum(balance_value) |
60 +--------------------+
61 | 22 |
62 +--------------------+
63 1 row in set (0.00 sec)

  三、 修改思路能夠簡化:仍是按以前的流程,只不過每個店鋪從頭至尾balancehistory的每一條記錄都賦上相應的值,爲了簡便計算.
    此外,在往balancehistory表中插入遺漏的記錄以前,還要先找出錯插的記錄(好比一個店鋪的記錄的店鋪id錯誤的記成了另一個店鋪的id),而後把店鋪id改爲正確的.

1 select id,create_time,shop_id,balance_type,balance_record,balance_value,customer_id,customer_totalPrice,shop_totalPrice,available_balance,is_cancel from balancehistory where shop_id = 1080 
2 order by create_time;
3 select sum(balance_value) from balancehistory where balance_type = 1 and customer_id = 2105 and shop_id = 1080;
4 select id,create_time,shop_id,balance_type,balance_record,balance_value,customer_id,customer_totalPrice,shop_totalPrice,available_balance,is_cancel from balancehistory order by 
5 shop_id,create_time;
6 select balance_record from balancehistory where balance_type = 3 and (balance_record not like '在線支付(微信):訂單%' or balance_record not like '在線支付(支付寶):訂單%');
7 
8 select id,create_time,shop_id,balance_type,balance_record,balance_value,customer_id,customer_totalPrice,shop_totalPrice,available_balance,is_cancel from balancehistory order by 
9 shop_id,create_time;

  四、 從數據庫中刪除數據示例:

1 self.session.query(models.CheckProfit).filter(models.CheckProfit.create_time == end_date,models.CheckProfit.is_checked==0).delete()

  五、 今日數據:快盤,github. 

【8.3 週一】

  一、 今日任務:總後臺銷售統計功能
    *框架搭建:url,頁面佈局,echarts框架
    *後臺數據獲取:數據獲取數據結果及算法

  二、 加功能流程:
  ①先肯定在哪一個模板網頁(xxxbase.html)上加功能(方法:根據要添加新功能頁面的url從urls.py文件中反查到對應的py文件中的類,而後到相應的py文件中找到這個類的get方法,到get方法的最後找到render方法,render方法中渲染的html頁面即爲當前的頁面,而後找到這個html頁面文件,便可找到它繼承的base頁面)--->②在該網頁上加上須要的html元素--->③在該網頁的頂部設置該元素的激活狀態變量,並設定激活條件,以及該元素的跳轉href名稱,這樣寫:href={{reverse_url('superCheckCash')}}--->④在urls.py中添加該名稱對應的路由以及superadmin.py中的新增長類的名稱--->⑤在superadmin.py中增長新的類,實現後臺功能.先從簡單開始,只寫get方法,return渲染到新頁面,以後再豐富功能--->⑥添加名字爲第⑤步中的渲染的網頁名稱的新網頁,引用須要的基本框架,在其中添加簡單的字符,以及在下方添加引用其對應的js文件--->⑦新建第⑥步中須要的js空文件--->⑧運行系統,看新增長的連接和頁面可否正常加載.若是正常加載,則進一步豐富系統功能(寫後臺post方法,html頁面的元素,js的事件處理等).

  三、 系統預約義的水果的名稱,id及其餘信息存在db_initdata.py文件中.

  四、 功能簡述:
    1.商品按類目銷售統計(按照日/周/月,分別統計不一樣時間段的系統中總銷售額前30名的商品類目及銷售額)
    2.同種類目商品銷售額前10名店鋪統計(按照日/周/月,分別統計不一樣時間段同種類目商品(限於1中的30個類目)銷售額達到系統前十名的店鋪的詳細信息)
    3.相同分組商品店鋪銷售額Top30店鋪
    4.不一樣分組商品銷售額排行(就三組:水果,乾果,其餘商品)(最後再加上個餅形圖)

  五、 注意事項:
    1.由於每一個店鋪的每單種商品的id具備惟一性,同一種商品(好比阿克蘇香梨)不一樣店鋪的叫法也可能不一樣,並且不一樣店鋪同一類目下的商品都不相同,因此總後臺的銷售統計中類目銷售統計不能統計類目下具體商品的銷售狀況.
    2.統計銷售額最大的前若干種商品具備現實意義,能夠經過分析不一樣時間(或季節)不一樣熱賣的商品的變化趨勢,得出一些有價值的結論,爲商城商家提供信息.
    3.由於圖表比較長,因此要加查看大圖功能.
    4.圖表名稱:
      商品銷售額Top30 - 按商品類目排序
      同類商品店鋪銷售額Top10 - 按店鋪名排序
      同組商品店鋪銷售額Top10 - 按店鋪名排序

  六、 微信公衆號文章排版工具:秀米

  七、 想要給總後臺的訂單統計的echarts添加loading,但改了半天發現出各類錯誤,仍是當初在似懂非懂的時候寫出的代碼太混亂了,結構不清晰,變量不規範,有必要進行重構.

  八、 今天總後臺訂單統計出現一個bug:下單時間曲線和收貨時間曲線又徹底同樣了,提示錯誤:KeyError:26
    立刻意識到又是數組下標越界了,把superadmin.py的954行左右的代碼改爲以下便可:
if order[1].hour + (order[1].minute+order[3])//60 >= 24:
data[order[1].hour + (order[1].minute+order[3])//60 - 24] += 1

【8.4 週二】
  一、 今日任務:總後臺銷售統計功能
  二、 後臺數據獲取算法:
    *銷售額Top30商品類目:
    (1)從fruit_type表中查出全部商品類目的id和名稱,存到一個字典fruit_type_price_dict中,鍵爲id,值爲名稱和銷售額組成的列表,且銷售額都初始化爲0.
      select id,name from fruit_type;
    (2)獲取指定時間段內的全部訂單的fruits字段和mgoods字段並分別存到兩個列表中:fruit_list,mgoods_list
    (3)從fruit_list列表的每一項中分離出charge_type_id和對應的金額,而後從charge_type_id反查到fruit_type_id,最後將fruit_type_price_dict中與此id相同的項的金額自加這個金額.
      計價方式-商品類目id對照表:select distinct charge_type.id,fruit_type_id from fruit,charge_type where fruit.id = charge_type.fruit_id;
    (4)從mgoods_list列表的每一項中分離出對應的金額,直接將fruit_type_price_dict中id=2000項(其餘商品)的金額自加這個金額.
    (5)將字典fruit_type_price_dict轉化成列表fruit_type_price_list,該列表的每個元素都爲一個子列表,子列表有三個元素:商品類目id,名稱,金額.將fruit_type_price_list列表按照每一項的金額降序排序,取前30個元素做爲output_data,返回給前臺.
    *同類商品銷售額Top10店鋪:
    (1)在網頁刷新的時候發一個post請求,用於獲取全部商品類目的id和名稱,按id升序排列,而後傳到js中爲下拉選擇二級菜單賦值,將類目名稱賦給下拉按鈕的text,將id賦給下拉按鈕的data-id屬性.令cur_selected_type_id = 當前顯示的選中那個類目的id.
    (2)經過post請求將cur_selected_type_id連帶其餘參數(起止時間等)傳到後臺,後臺shop_count方法進行處理.
    (3)先從fruit表和charge_type表聯合查詢查出全部fruit_type_id等於cur_selected_type_id的charge_type.id,shop_id,並創建一個字典charge_type_shop_dict,該字典的鍵是charge_type.id,值是一個列表,列表的第一項是shop_id,第二項是金額,初始化爲0.
select charge_type.id,shop_id from charge_type,fruit where charge_type.fruit_id = fruit.id;
    (4)用self.get_order方法獲取選取時間段的全部訂單的fruits字段和mgoods字段並存入fruit_list和mgoods_list中,並判斷若是cur_selected_type_id != 2000則不對mgoods進行處理,只對fruit_list進行處理.
    (5)從fruit_list列表的每一項中分離出charge_type_id和對應的金額,而後將charge_type_shop_dict鍵等於charge_type_id的項的金額自加對應的金額.若是查不到計價方式對應的shop_id(可能計價方式已經被刪除了)那麼直接continue.須要創建一個列表cur_charge_type_list,該列表包含cur_selected_type_id對應的全部計價方式的id.
    (6)將字典charge_type_shop_dict的值([shop_id,price])存到一個列表中,考慮到shop_id會有重複的狀況(由於同一個charge_type_id可能對應多個shop_id),因此先要把shop_id存到一個列表cur_shop_id中,而後將該列表去重,而後再遍歷charge_type_shop_dict的值,累加每一個店鋪的price,存到each_shop_price_dict字典中,鍵爲shop_id,值爲price.
    (7)若是cur_selected_type_id == 2000:從m_charge_type,m_goods,menu三表聯合查詢,查出全部m_charge_type中id對應的menu表中的shop_id,並創建字典,鍵爲m_charge_type_id,值爲shop_id,而後根據shop_id將金額累加到charge_type_shop_dict中去.若是查不到計價方式對應的shop_id(可能計價方式已經被刪除了)那麼直接continue.
完了之後再遍歷當前字典,若是shop_id在each_shop_price_dict的鍵列表中,則將這這個鍵對應的price自加,不然新增鍵值對.
    (8)最後新建一個列表each_shop_price_list,每個元素爲一個子列表,子列表的第一項爲shop_id,第二項爲shop_name,第三項爲price,將each_shop_price_list按照price降序排列,而後取each_shop_price_list的前十項返回到前臺.
    *同組商品銷售額Top10店鋪:
    (1)先設定三個分組的id:水果1,乾果2,其餘商品0,頁面刷新的時候前臺就發post請求,傳分組id,而後後臺group_count方法進行處理
    (2)後面處理算法與前面相似.

  三、 注意事項:
    (1)fruit_type_id < 999:水果
    (2)fruit_type_id = 999:其餘水果
    (3)1000 < fruit_type_id < 1999:乾果
    (4)fruit_type_id = 1999:其餘乾果
    (5)fruit_type_id = 2000:其餘商品
    (6)以前的mgoods如今都算成是'其餘商品'
    (7)有大量的fruits字段中的計價方式被刪掉了,這樣就找不到該種水果所屬的類別了,那金額就統一歸爲'其餘水果'的類目中.
    (8)第二個圖的下拉選項按鈕考慮用二級菜單實現,列出全部的商品類目供選擇.

  四、 python在當前類中調用當前類的其餘方法,在其餘方法名前必定要加'self.'才行,不然會提示方法未定義.

  五、 jquery兩個關聯元素綁定hover事件(這個問題好麻煩,網上找了不少資料都很麻煩,最後發現了setTimeout函數)
    解決方案1:用延時函數解決.

1 setTimeout(function(){
2 ... //這裏是要延時500ms執行的代碼
3 },500);

    由於給第二級菜單加了mouseover事件來顯示第三級菜單,同時也給第二級菜單加了mouseleave事件在鼠標離開第二級菜單的時候隱藏第三級菜單,可是在鼠標從第二級菜單向第三級菜單移動的時候,原本是不指望隱藏掉第三級菜單的,由於那樣就找不到第三級菜單了,因此爲第二級菜單的mouseleave事件加上延時,這樣鼠標指針就能夠在第三級菜單隱藏掉以前滑到它上面,同時在第二級菜單的延時時間到達的那一瞬間用show()方法顯示.這樣就解決了問題,可是會出現閃爍的現象.

    解決方案2:用聯動的addClass("hidden")和removeClass("hidden")方法實現,此種方法能夠方案一的閃爍現象,但也有缺陷.
         假設第二級菜單有兩個選項,id分別爲second1,second2,點擊second1,second2彈出的第三級菜單的id分別爲third1,third2,先給second1添加mouseover事件:

1 $("#third1").removeClass("hidden");
2 $("#third2").addClass("hidden");
3 //再給third1添加mouseover事件:
4 $("third1").removeClass("hidden")
5 //給third1添加mouseout事件:
6 $("third1).addClass("hidden")

         對second2和third2的處理同理,只要保證third1和third2的隱藏和消失互斥便可.

【8.5 週三】
  一、 今日任務:總後臺銷售統計

  二、 jquery有時候要顯示一個元素,僅僅使用removeClass("hidden")屬性是無論用的,display屬性仍然爲none,還要再加個show()方法.

  三、 jquery display:none與visible:hidden的區別:
    display:none和visible:hidden都能把網頁上某個元素隱藏起來,但二者有區別:
    display:none --- 不爲被隱藏的對象保留其物理空間,即該對象在頁面上完全消失,通俗來講就是看不見也摸不到。
    visible:hidden--- 使對象在網頁上不可見,但該對象在網頁上所佔的空間沒有改變,通俗來講就是看不見但摸獲得。
    例子:

1 <html>
2 <head>
3 <title>display:none和visible:hidden的區別</title>
4 </head>
5 <body >
6 <span style="display:none; background-color:Blue">隱藏區域,同時把位置讓出來</span><span style=" background-color:Green">顯示區域,顯示的地方會佔據原先隱藏區域的位置</span><br />
7 <span style="visibility:hidden; background-color:Blue">隱藏區域,雖然隱藏可是位置依然佔着</span><span style="background-color:Green">顯示區域</span>
8 </body>
9 </html>

  四、 jquery中調用post方法所在的函數可能會出現這個問題:
    前一個調用尚未執行完(好比由於數據量大等因素),後一個調用緊接着就執行了,這會帶來相互之間的影響,引起未知的錯誤.
    能夠這樣解決:定義一個全局的標誌變量,相似於一個鎖,用該變量的狀態控制每次的調用是否可以執行便可.或者關閉異步:$.ajaxSetup({async:false});

  五、 用echarts的hideLoading方法時遇到一個奇怪的問題:刷新頁面的時候js出現異常,出現錯誤:

1 Uncaught TypeError: Cannot read property 'hideLoading' of null(anonymous function) @ superadmin-count_sell.js?v=03a80c5e1ec3f44ec6876f69099b1146:862m.Callbacks.j @ jquery.min.js:2m.Callbacks.k.fireWith @ jquery.min.js:2x @ jquery.min.js:4m.ajaxTransport.send.b @ jquery.min.js:4
2 echarts.js:1 Dom’s width & height should be ready before init.

    並且這個問題有時出現有時又正常.
    但當點擊選項的時候調用一樣的post請求函數,又恢復正常.
    最後發現問題出在:初始化echarts的時候沒有爲echarts所在的div設定高度,致使echarts初始化失敗,只需提早爲div設置高度便可.
    但偶爾數據返回成功之後,還會出現異常:Uncaught TypeError: Cannot read property 'hideLoading' of null,也就是echarts仍是沒有初始化成功.這個異常只是偶爾出現,別的時候恢復正常,但是這更加讓人困惑.
    找了半天緣由發現有這麼一個現象:在瀏覽器中用ctrl+R或者f5刷新纔會偶爾出現上述問題,而從get方法進入或者從url回車進入並不會出現這個問題,因此猜想多是用ctrl+R或f5刷新的時候致使瀏覽器強制清空了變量的緩存,而這時函數可能尚未執行完,接着再執行到了用到剛剛清空了緩存的變量的地方,就會出現變量詭異的變成了null的現象.
    並且還有就是作店鋪後臺銷售統計的時候也並無提早設置高度,並且沒有出現異常,這個問題有待進一步探究.
    後來研究echarts官網的demo發現,返回數據後須要對hideLoading方法進行一個延時處理,因此考慮多是由於echarts異步刷新的問題,可是延時處理之後還會偶爾出現異常,也多是echarts的一個bug.

  六、 在瀏覽器中打開一個純文本txt編輯器頁面:
    在地址欄中輸入:data:text/html, <textarea style='height:100%;width:100%;margin:auto'></textarea>而後回車便可;
    若是想保留文本的格式和圖片,則只需輸入這行代碼便可:data:text/html, <html contenteditable>
    還能夠把這兩個頁面保存爲書籤,或在輸入內容之後保存成文件,之後點開就能用.

  七、 總後臺添加了省級代理管理員,增長管理員的level(總超級管理員:0,省級代理管理員:1,已刪除:-1)

1 self.current_user.level
2 shop_province = self.current_user.province

【8.6 週四】
  一、 今日任務:
    (1)已經完成了總後臺銷售統計功能,可是考慮到系統新增長了總後臺省級代理管理員,因此要根據管理員的level和province對數據進行篩選.
    (2)爲店鋪後臺-商品管理-商品分組中的分組添加連接,跳轉到'全部商品'並顯示相應分組的商品.
    (3)店鋪後臺-商品關聯-全部商品的排序有bug,修復之.
  二、 根據總後臺管理員的level和province對數據進行篩選的基本方式舉例:

1 level = self.current_user.level
2 shop_provice = self.current_user.province
3 if level == 0:
4   order_list_data = self.session.query(models.Order).filter(models.Order.status == 6).order_by(desc(models.Order.comment_create_date))
5 elif level == 1:
6   order_list_data = self.session.query(models.Order).join(models.Shop,models.Order.shop_id == models.Shop.id).filter(models.Order.status == 6,models.Shop.shop_province == shop_province).distinct(models.Order.id).order_by(desc(models.Order.comment_create_date))

    測試用數據:level = 1,shop_province = 420000

  三、 完成數據分省篩選!

  四、 echarts中series添加屬性barWidth:[number]能夠設置柱狀條的寬度.

  五、 sqlalchemy三表聯合查詢示例:

1 query_list = self.session.query(models.TableA.a_name).join(models.TableB,models.TableA.b_id == models.TableB.id).join(models.TableC,models.TableB.c_id = models.TableC.id).filter(models.TableC.name == 'ccc').all()

  六、 html中如何讓鼠標箭頭移到某個div上就變爲手型,移出後再變爲原型:給這個div的樣式加一條:'cursor:pointer;'若是被覆蓋了,就在pointer後面加一個'!important'

  七、 jquery中網址跳轉示例('?'後面的是參數):window.location.href = "/admin?data=data_str&&page=0";

  八、 jquery,點擊DIV觸發事件,可是點擊DIV的子元素不觸發事件,該如何寫選擇器?
    解決方法:即取消事件冒泡:

1 $('.div a').click(function(e){
2 e.stopPropagation();
3    ...//a標籤的其餘事件處理
4 });

    而後爲div添加點擊事件便可.
    主要就是讓a標籤點擊了之後中止冒泡,'.div'就是a標籤外層容器的class.

  九、 chrome事件調試:
    在要檢查的元素上單擊右鍵選擇查看元素,而後,右邊的面板中會顯示style標籤,切換到EventListenrs標籤,能夠看到相關的事件綁定信息。點擊最右邊的文件名稱還能夠跳轉到事件定義代碼在腳本文件中的位置。
    或者能夠使用一個更強大的插件:chrome VisualEvent,直接搜索VisualEvent.crx下載後直接拖放到瀏覽器中安裝便可.

  十、 util.js裏面有不少好方法.
      base.py裏面也有不少好方法.

【8.7 週五】
  今日任務:店鋪後臺-商品關聯-全部商品的排序有bug,修復之.
  一、 關於reverse_url和static_url兩個函數:
    (1)reverse_url:
      ①在goods-set-base.html中,有幾個連接,其中用到reverse_url函數:

1 <ul class="subnav pull-left order-type">
2 <li class="text-center aall"><a href="{{reverse_url('adminGoods')}}">全部商品</a></li>
3 <li class="text-center agroup"><a href="{{reverse_url('adminGoodsGroup')}}">商品分組</a></li>
4 <li class="text-center adelete"><a href="{{reverse_url('adminGoodsDelete')}}">已刪除商品</a></li>
5 <li class="text-center ml40 aclassify"><a href="{{reverse_url('adminGoodsClassify')}}">商品類目</a></li>
6 </ul>

      ②在urls.py中有以下幾個url:

1 ...
2 (r"/admin/goods/all", handlers.admin.Goods, {"action":"all"}, "adminGoods"),
3 (r"/admin/goods/classify", handlers.admin.Goods, {"action":"classify"}, "adminGoodsClassify"),
4 (r"/admin/goods/group", handlers.admin.Goods, {"action":"group"}, "adminGoodsGroup"),
5 (r"/admin/goods/delete", handlers.admin.Goods, {"action":"delete"}, "adminGoodsDelete"),
6 ...

      ③在admin.py的Goods類中,有初始化方法:

1 @tornado.web.authenticated
2 def initialize(self,action);
3   self._action = action

      ④在Goods類的get方法中調用action:

1 @AdminBaseHandler.check_arguments(...)
2 def get(self):
3     action = self._action
4     ...

      ⑤reverse_url是tornado自帶的函數,用來根據name來反查url.
    (2)static_url,也是tornado自帶的函數:
      ①在application.py文件的setting中有:static_path=os.path.join(os.path.dirname(__file__),"static")
      ②在template/index.html中有:

1 <head>
2 <link rel="stylesheet" type="text/css" href="{{ static_url('css/style.css')}}">
3 <head>

  二、 python銷燬一個變量x:del x

  三、 js中ajax的使用:

 1 function getData(action,id,page){
 2 var url;
 3 url = "/admin/goods/all?action=" + action + "&id=" + id + "&page=" + page;
 4 $.ajax({
 5 url:url,
 6 type:"get",
 7 success:function(res){
 8 if(res.success){
 9 output_data = res.output_data;
10 console.log(output_data);
11 }
12 else{
13 Tip(res.error_text);
14 }
15 }
16 })    
17 }

    而後在後臺的相應類的get方法中要這樣寫:

1 ...
2 @AdminBaseHandler.check_arguments("action:str","id:int","page:int")
3 def get(self):
4     action = self.args["action"]
5     id = self.args["id"]
6     page = self.args["page"]
7     output_data = [action,id,page]
8     return self.render("admin/goods-all.html",output_data=output_data)
9     ...

  四、 js實現這樣一個功能:點擊一個頁面A中的a標籤跳到另一個頁面B,同時向B頁面的後臺發送請求返回相應的數據刷新頁面:
    (1)在A頁面的html文件中爲要添加跳轉連接的a標籤的href屬性賦值(包括js中動態添加的a標籤也要賦值),其中前半部分爲要跳轉到的B頁面的url,後半部分爲自定義的要傳遞的參數.這裏的data["user_id"]須要提早向A頁面的後臺請求獲取到.

1 <a href="/super/user?out_link=true&&data_id={{data["user_id"]}}" ...>...</a>

    或者用reverse_url函數:

1 <a href="{{reverse_url('superUser')}}?out_link=true&&data_id={{data["user_id"]}}" ...>...</a>

    (2)在B頁面的js中的$(document).ready(function(){})中添加相似於以下的代碼:

1 var out_link = $.getUrlParam("out_link");
2 if(out_link == "true"){
3 var data_id = $.getUrlParam("data_id");
4 page = 0;
5 getSearchContent('out_link',data_id,page); //這裏getSearchContent爲B頁面的js中原來就有的搜索函數,這裏借用一下,只是把action
6 //從'search'改爲了'out_link',把傳給後臺的參數從inputinfo改爲了data_id
7 //固然也能夠本身從新再寫一個函數向後臺請求數據.
8 }

    (3)在B頁面的後臺中,增長以下代碼:

1 ...
2 action = self.args["action"]
3 ...
4 if action == "out_link":
5 user_id = int(self.args["inputinfo"])  //這裏的參數inputinfo正是(2)中js傳過來的參數data_id.
6 q = q.filter(models.Accountinfo.id == user_id)
7 ... #後面的是對q進行處理從而返回給js數據的代碼

    注:跳轉後要把跳轉到的頁面的"上一頁/下一頁"按鈕隱藏掉

  五、 python eval函數的強大:
    能夠將字符串str當成有效的表達式來求值並返回計算結果。
    例如:

1 if sort_way = "group":
2     case = 'models.Fruit.group_id'
3 elif sort_way = "type":
4     case = 'models.Fruit.fruit_type_id'
5     goods = self.session.query(models.Fruit.name).order_by(eval(case_one)).all()

  六、 mysql中按照拼音排序的方法:
    select name from user order by convert(name using gbk) asc;
    但這種方法在sqlalchemy中用不了,不管是這樣用:
      name_list = self.session.query(models.User.name).order_by(func.convert(models.User.name.using('gbk'))
    仍是這樣用:
      name_list = self.session.query(models.User.name).order_by(func.convert(models.User.name,'gbk'))
    或者這樣用:
      name_list = self.session.query(models.User.name).order_by(func.convert(models.User.name,'gbk','utf-8'))
    或者這樣用:
      name_list = self.session.query(models.User.name).order_by(func.encode(models.User.name,'gbk'))
    結果都會報錯,看來sqlalchemy是不支持這種編碼轉換的.

【8.8 週六】

  一、 python 3中只有unicode str,把decode方法去掉了
  二、 python多維排序示例(用operator):

1 >>> from operator import itemgetter
2 >>> c = [[1,2,5],[2,43,23],[1,1,32],[3,34,6],[3,2,5],[3,2,4]]
3 >>> c.sort(key=operator.itemgetter(0,1,2))
4 >>> c
5 [[1, 1, 32], [1, 2, 5], [2, 43, 23], [3, 2, 4], [3, 2, 5], [3, 34, 6]]
6 >>> b = [{'b': 211, 'a': 100}, {'b': 21, 'a': 100}, {'b': 323, 'a': 101}, {'b': 12, 'a': 100}]
7 >>> b.sort(key = itemgetter('a','b'))
8 >>> b
9 [{'b': 12, 'a': 100}, {'b': 21, 'a': 100}, {'b': 211, 'a': 100}, {'b': 323, 'a': 101}]

  三、 由於gbk/gb2312的坑爹編碼方式,前幾千個一級漢子是連續的且按拼音排序的,但後面的漢子卻不是按照拼音排序的,因此中文拼音排序仍然仍是一個問題,有待解決.

  四、 gb2312是gbk的子集,二者都是16位的,gbk是gb18030的子集,gb18030是32位的.

  五、 總後臺用戶名連接的精確跳轉的a標籤href屬性設置:

1 href="/super/user?out_link=true&&data_id={{shop.admin.accountinfo.id}}" target="_blank" title="點擊查看用戶詳細信息"
2 href="{{reverse_url('superUser')}}?out_link=true&&data_id={{shop.admin.accountinfo.id}}" target="_blank" title="點擊查看用戶詳細信息"

 

【8.10 週一】

  一、 sqlalchemy執行原生sql語句的方法:

1 entries = self.session.execute("select name from fruit where shop_id = 4")
2 print(entries)
3 for item in entries:
4    print(item)

    輸出結果爲:
    <sqlalchemy.engine.result.ResultProxy object at 0x7f771a669860>
  二、 近期的店鋪後臺加了防DDoS攻擊的代碼,所以致使若是後臺操做過於頻繁會出現503錯誤,以前寫的銷售統計也會出現這個問題.
    解決方法:在js中每次發post請求以前都進行延時(這裏延時了250ms)
  三、 503錯誤:503 (Service Temporarily Unavailable):
    日誌文件中,其中的s-reason項:
    (1)若爲AppShutdown,多是因爲CPU佔用率過高致使自動關閉應用程序池。
    (2)若爲AppOffline,多是因爲應用程序標識出錯引發的。
    (3)若爲Disabled,多是由管理員手工關閉應用程序池引發的。
    (4)若爲QueueFull,多是由於請求時應用程序池隊列已滿而生成該錯誤。
  四、 DDos攻擊的比喻說明:
  一羣惡霸試圖讓對面那家有着競爭關係的商鋪沒法正常營業,他們會採起什麼手段呢?(只爲舉例,切勿模仿)惡霸們扮做普通客戶一直擁擠在對手的商鋪,賴着不走,真正的購物者卻沒法進入;或者老是和營業員有一搭沒一搭的東扯西扯,讓工做人員不能正常服務客戶;也能夠爲商鋪的經營者提供虛假信息,商鋪的上上下下忙成一團以後卻發現都是一場空,最終跑了真正的大客戶,損失慘重。此外惡霸們完成這些壞事有時憑單幹難以完成,須要叫上不少人一塊兒。嗯,網絡安全領域中DoS和DDoS攻擊就遵循着這些思路。
  在信息安全的三要素——「保密性」、「完整性」和「可用性」中,DoS(Denial of Service),即拒絕服務攻擊,針對的目標正是「可用性」。該攻擊方式利用目標系統網絡服務功能缺陷或者直接消耗其系統資源,使得該目標系統沒法提供正常的服務。
  DdoS的攻擊方式有不少種,最基本的DoS攻擊就是利用合理的服務請求來佔用過多的服務資源,從而使合法用戶沒法獲得服務的響應。單一的DoS攻擊通常是採用一對一方式的,當攻擊目標CPU速度低、內存小或者網絡帶寬小等等各項指標不高的性能,它的效果是明顯的。隨着計算機與網絡技術的發展,計算機的處理能力迅速增加,內存大大增長,同時也出現了千兆級別的網絡,這使得DoS攻擊的困難程度加大了-目標對惡意攻擊包的"消化能力"增強了很多。這時候分佈式的拒絕服務攻擊手段(DDoS)就應運而生了。DDoS就是利用更多的傀儡機(肉雞)來發起進攻,以比從前更大的規模來進攻受害者.
  五、 總後臺餘額和對帳有bug,提示404錯誤和一個返回數據undefined錯誤.
    錯誤緣由:一個公用的html文件引入了子html文件的js,致使查詢不到數據,把這個多餘的js去掉便可.
  六、 如何提升python服務器的併發度?瓶頸在哪?如何打破瓶頸?
    node.js和python的區別.
    操做系統/linux的知識.
    緩存持久化
  七、 壓縮的js或html文件還原工具:http://jsbeautifier.org/
  八、 新功能:後臺-用戶管理的排序規則完善:建議添加用戶積分、充值金額的排序規則.
  九、 用get方法代替post,比較簡單!方法總結.
  十、 聯合查詢後的分頁問題(分頁錯亂).
【8.11 週二】

  今日任務:de各類bug,增長店鋪後臺用戶管理的排序功能.
  新功能:商品秒殺的店鋪後臺前端與後端實現.
  一、 昨天的任務完成!分頁錯亂的問題是由於聯合查詢的時候沒有篩選店鋪id致使的.
  二、 下拉選擇按鈕的實現總結:
  (1)首先在html的適當位置加入以下代碼:

 1 <li class="pull-right set-right10"> 
 2         <div class="tit cate-title">排序規則:</div>
 3         <div class="dropdown slide-down-select w130">
 4                 <button class="btn btn-default dropdown-toggle area height25 slide-btn" type="button" id="dropdownMenu1" data-toggle="dropdown">
 5                     <em class="pull-left filter_status" id="cur-sort-way" data-id="time">關注時間</em>
 6                     <span class="caret pull-right no-margin-left rotate0"></span>
 7                 </button>
 8                 <ul class="dropdown-menu dropdown-menu-right w130 condition-list" role="menu" aria-labelledby="dropdownMenu1" id="sort-way-list">
 9                         <li data-id="time"><a class="item sort-time">關注時間</a></li>
10                         <li data-id="point"><a class="item sort-point">用戶積分</a></li>
11                         <li data-id="balance"><a class="item sort-balance">帳戶餘額</a></li>
12                 </ul>
13         </div>
14 </li>

    分析:①最外層的li有兩個css屬性,分別是向右浮動和右邊距爲10.css樣式以下:
        .pull-right{float:right !important;}
        .set-right10{margin-right:10px;}
      ②第一個div有兩個css屬性,分別以下:
        .tit{display:inline-block;overflow:hidden;}
        .cate-title{font-size: 14px;color: #999;height: 28px;line-height: 28px;float: left;margin-right: 5px;}
      ③第三個div,有三個css屬性,第一個屬性用於下面的判斷,後面兩個屬性分別以下:
        .slide-down-select{display:inline-block;width:100%;background:#fff;color:#000;border:1px solid #ddd;margin-left:0;}
        .w130{width:130px !important;}
      ④button中有不少屬性,btn屬性以下:
        .btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none; -ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius: 6px;}
      ⑤btn-default屬性以下(應該是bootstrap自帶屬性):
        .btn-default{color:#333;background-color:#fff;border-color:#ccc}
        data-toggle爲數據切換屬性.
      ⑥其餘屬性以下:
        .dropdown-toggle{padding:0 4px;}
        .area{display:inline-block;width:100%;background:#fff;color:#222;border:1px solid #e7e7eb;margin-left:0;}
        .height25{height:25px;}
        .slide-down-select .slide-btn{height: 24px;line-height: 24px;display: block;border: none;outline: none;width: 100%;}
      ⑦全部屬性整理以下:

 1 .dropdown-menu{overflow: hidden;max-height: 210px;overflow-y: auto;}
 2 .category-list>li{float: left;width: 25%;}
 3 
 4 .cate-title{font-size: 14px;color: #999;height: 28px;line-height: 28px;float: left;margin-right: 5px;}
 5 .slide-down-select{display:inline-block;width:100%;background:#fff;color:#000;border:1px solid #ddd;margin-left:0;}
 6 .slide-down-select .slide-btn{height: 24px;line-height: 24px;display: block;border: none;outline: none;width: 100%;}
 7 .slide-down-select em{font-style:normal;display:inline-block;width:110px;font-size:14px;overflow:hidden;padding-left: 10px;text-align: left;}
 8 
 9 .dropdown-toggle{padding:0 4px;}
10 .dropdown-menu li{width:100%;padding:0;}
11 .dropdown-menu .item{padding-left:14px;}
12 .dropdown-menu li a:hover{color:#fff;background-color: #6ba4ef;}
13 .caret{margin-top:10px;color: #c6c6c6;}
14 .borderc{border: 1px solid #e7e7eb;}
15 .pointer{cursor: pointer;}
16 .min80{min-width: 80px;}
17 .mt2{margin-top: 2px;}
18 .txt-center{text-align: center !important;}
19 .txt-left{text-align: left !important;}
20 .hig{border: 1px dashed #ff6666 !important;}
21 .no-title{font-size: 20px;text-align: center;margin-top: 40px;color: #333;}
22 
23 .pull-left{float:left !important;}
24 .w130{width:130px !important;}
25 .ml20{margin-left: 20px;}

    (2)而後在js中要爲ul中的li添加點擊事件,點擊事件要作兩件事,一是點擊的時候爲em的text賦值爲當前li的a標籤的text,二是要調用相關函數向後臺發post請求顯示數據.
    (3)ul在一開始的時候也能夠是空的,在js中先向後臺發post請求獲取ul的項的數據,而後在js中動態添加上去,再添加點擊事件.
  三、 用get方法替代post方法請求數據的方法(這種方法特別適合於頁面結構特別複雜,寫artTemplate很困難的狀況的數據請求,也適合於翻頁的數據請求):
    (1)先在後臺寫get方法,設置所需的參數檢查,好比:
      @AdminBaseHandler.check_arguments("order_by:str","page:int")
      其中order_by表示在url中的排序方式參數,page表示頁碼.
    (2)在get方法中根據order_by和page向數據庫查詢數據,並作排序和分頁處理,而後用數據渲染頁面.
    (3)在js中,將order_by和page設置爲全局變量,利用下拉選項按鈕的點擊事件改變order_by的值,利用上一頁和下一頁按鈕的點擊事件改變page的值,而後在這些點擊事件中用這樣的方法向後臺請求數據和刷新頁面:
      var url = "/XXX?order_by="+order_by+"&&page="+page;
      window.location.href = url;
    固然這只是一個簡單的例子,還能夠添加更爲複雜的參數.
    注:在後臺參數檢查的時候判斷某一個參數是否不在參數列表中的方法:
    if 'page' in self.args:
       ...
  四、 數據庫聯合查詢:

 1 (1)mysql中,創建了兩個表A和B:
 2 create table A (aID int auto_increment primary key,aNum char(10));
 3 create table B(bID int not null auto_increment primary key,bName char(10));
 4 (2)向A和B表中插入數據,結果以下:
 5 mysql> select * from A;
 6 +-----+------+
 7 | aID | aNum |
 8 +-----+------+
 9 |   1 | a101 |
10 |   2 | a102 |
11 |   3 | a103 |
12 |   4 | a104 |
13 |   5 | a105 |
14 +-----+------+
15 
16 mysql> select * from B;
17 +-----+-------+
18 | bID | bName |
19 +-----+-------+
20 |   1 | b201  |
21 |   2 | b202  |
22 |   3 | b203  |
23 |   4 | b204  |
24 |   8 | b209  |
25 +-----+-------+
26 
27 (3)測試左聯接(left join):
28 mysql> select * from A left join B on A.aID = B.bID;
29 +-----+------+------+-------+
30 | aID | aNum | bID  | bName |
31 +-----+------+------+-------+
32 |   1 | a101 |    1 | b201  |
33 |   2 | a102 |    2 | b202  |
34 |   3 | a103 |    3 | b203  |
35 |   4 | a104 |    4 | b204  |
36 |   5 | a105 | NULL | NULL  |
37 +-----+------+------+-------+
38 5 rows in set (0.00 sec)
39 結果分析:left join是以A表的記錄爲基礎的,A表能夠當作是左表,B表能夠當作是右表,left join是以左表爲基準的.換句話說,做爲基準的左表(A)的記錄將會所有表示出來,而右表(B)
40 
41 只會顯示符合搜索條件的記錄(上例中爲:B.bID=A.aID),B表沒有記錄的地方都爲NULL.
42 
43 (4)測試右聯接(right join):
44 mysql> select * from A right join B on A.aID = B.bID;
45 +------+------+-----+-------+
46 | aID  | aNum | bID | bName |
47 +------+------+-----+-------+
48 |    1 | a101 |   1 | b201  |
49 |    2 | a102 |   2 | b202  |
50 |    3 | a103 |   3 | b203  |
51 |    4 | a104 |   4 | b204  |
52 | NULL | NULL |   8 | b209  |
53 +------+------+-----+-------+
54 5 rows in set (0.00 sec)
55 結果分析:恰好和left join的結果相反,此次是以右表(B)爲基準的,A表不足的地方用NULL填充.
56 
57 
58 (5)測試inner join(相等聯接或內聯接)
59 mysql> select * from A inner join B on A.aID = B.bID;
60 +-----+------+-----+-------+
61 | aID | aNum | bID | bName |
62 +-----+------+-----+-------+
63 |   1 | a101 |   1 | b201  |
64 |   2 | a102 |   2 | b202  |
65 |   3 | a103 |   3 | b203  |
66 |   4 | a104 |   4 | b204  |
67 +-----+------+-----+-------+
68 4 rows in set (0.00 sec)
69 結果分析:此次只列出了A.aID和B.bID相等且不爲NULL的記錄,並不以哪一個表爲基準.
70 
71 注:數據庫中表名是分大小寫的.
72 sqlalchemy中只有join和outerjoin(爲左外聯接).

  五、 QQ分享API

 1 <script type="text/javascript">
 2 (function(){
 3 var p = {
 4 url:location.href, /*獲取URL,可加上來自分享到QQ標識,方便統計*/
 5 desc:'', /*分享理由(風格應模擬用戶對話),支持多分享語隨機展示(使用|分隔)*/
 6 title:'', /*分享標題(可選)*/
 7 summary:'', /*分享摘要(可選)*/
 8 pics:'', /*分享圖片(可選)*/
 9 flash: '', /*視頻地址(可選)*/
10 site:'', /*分享來源(可選) 如:QQ分享*/
11 style:'101',
12 width:96,
13 height:24
14 };
15 var s = [];
16 for(var i in p){
17 s.push(i + '=' + encodeURIComponent(p[i]||''));
18 }
19 document.write(['<a class="qcShareQQDiv" href="http://connect.qq.com/widget/shareqq/index.html?',s.join('&'),'" target="_blank">分享到QQ</a>'].join(''));
20 })();
21 </script>
22 <script src="http://connect.qq.com/widget/loader/loader.js" widget="shareqq" charset="utf-8"></script>

  六、 商品秒殺(seckill)任務分析:
    (1)原型圖中'點擊查看使用教程'的跳轉連接爲:'/bbs/detail/xxx',其中'xxx'爲bbs中教程的編號,是一個整數.
    (2)原型-秒殺管理中,列表中'秒殺商品後面的數字去掉;'領取/下單/庫存'列的數值爲秒殺商品的總數.
      ('領取'是個什麼意思??)
    (3)當過了秒殺的時間,該行秒殺管理文字顏色所有變爲灰色,操做爲:'已結束'.
    (4)當點擊'停用'時,該行秒殺管理文字所有變爲灰色,操做爲:'已失效'.
    (5)未開始狀態下,'編輯'的選項均可使用;進行中,只能編輯庫存.
    (6))原型-新建秒殺中,商品名須要細分至具體的商品名,不能爲整組秒殺(這裏的商品名是指商品類目名仍是單個商品名??)
    (7)原型-新建秒殺中,原價顯示該商品全部的價格,爲單選.
    (8)數據庫表設計:
    *表名:seckill
    *各列分析:

 1 id(該條秒殺數據項的id,id=Column(Integer,nullable=False,primary_key=True))
 2 activity_id(秒殺活動id,不具備惟一性,能夠有多行的activity_id相同,activity_id=Column(Integer,nullable=False);設定activity_id爲當前秒殺的店鋪id字符串加上當前秒殺活動的整形時間戳字符串)
 3 shop_id(該條秒殺所在的店鋪的id,shop_id=Column(Integer,nullable=False))
 4 start_time(秒殺開始時間,時間戳類型,start_time=Column(Integer))
 5 end_time(秒殺結束時間,時間戳類型,end_time=Column(Integer))
 6 continue_time(秒殺持續的時間,時間戳類型,continue_time=Column(Integer))
 7 fruit_id(商品id,fruit_id = Column(Integer,ForeignKey(Fruit.id)))
 8 charge_type_id(當前秒殺商品的計價方式id,charge_type_id = Column(Integer,ForeignKey(ChargeType.id)))
 9 former_price(原價,浮點型,former_price=Column(Float))
10 seckill_price(秒殺價,浮點型,計價方式與former_price相同,seckill_price=Column(Float))
11 storage_piece(剩餘庫存換算成當前計價方式的份數,浮點型,storage_piece=Column(Float))
12 activity_piece(活動庫存的份數,浮點型,activity_piece=Column(Float))
13 status(當前秒殺商品的狀態,整形,status = Column(TINYINT);取值:-1(已停用),0(已結束),1(未開始),2(進行中))

    (9)'推廣'連接跳到'發現'頁面.
    (10)marketing表中新增長一個字段,控制店鋪秒殺活動是否開啓:seckill_active=Column(Integer,default=1) #0:關閉  1:開啓
  七、 注意事項:
    (1)由於秒殺對時間的精度要求比較高,因此數據庫中用時間戳存儲和時間日期有關的數據.
  八、和時間戳有關的函數:
    ①時間戳轉換成datetime格式的字符串:
      重寫base.py中GlobalBaseHandler類中的timestamp_to_str方法(原方法中沒有精確到秒):
      def timestamp_to_str(self, timestamp):
         return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(timestamp))
      或者使用該類中的通用工具函數code_to_text(column_name,code),調用時候column_name爲'create_date_timestamp',code爲整形的時間戳.
    ②獲取當前時間的時間戳:now = datetime.datetime.now().timestamp()
    ③將時間戳轉化爲日期:
      b_time_stamp = 776361600
      dateArray = datetime.datetime.utcfromtimestamp(b_time_stamp)
      birthday = dateArray.strftime("%Y年%m月%d日")
      print(birthday)
      輸出:1994年08月08日
    ④mysql把時間戳轉化爲日期:
      mysql>SELECT FROM_UNIXTIME( 1249488000, '%Y-%m-%d' ) 
      ->2007-11-20

【8.12 週三】

  今日任務:商品秒殺
  一、 wdatepicker只顯示時分秒
  二、 選中時候爲綠色的方形單選按鈕;switch開關按鈕;
  三、 確認對話框的使用:
  四、 js查找離最近的具備某種屬性的元素:

1 $( document ).bind("click", function( e ) {
2     $( e.target ).closest("li").toggleClass("hilight");
3 });

  五、 jquery查找具備某種屬性的元素的個數:
    $(".new-seckill-item").length
  六、 jquery not()方法:
    從包含全部段落的集合中刪除 id 爲 "selected" 的段落:
      $("p").not("#selected")
  七、 jquery可見性篩選:
    全部可見的表格:
      $("table:visible")
  八、 使用jquery prev()方法找到同級的前一個元素:
    $("p").prev(".selected")
  九、 jquery查找當前元素相對於第一個具備屬性aaa的元素的index值:
    $(".aaa").index($this);
  十、 jquery獲取第i個有屬性aaa的元素:
    $(".aaa:eq(" + i+ ")");
  十一、 datePicker最小時間要爲當前時間
  十二、 商品計價方式代碼-漢字轉換在base.py基類中有一個方法。
  1三、 店鋪推薦和默認分組這兩個分組在goods_group表中是沒有的,它們在group_priority表中:
      id = -1:推薦分組
      id = 0:默認分組
  1四、 python將列表轉換成字典:
      lista = [(-1, '推薦分組'), (0, '默認分組'), (22, '水果單品'), (25, '青年果汁'), (26, '青年果切')]
      lista = dict(lista)
    執行操做後,lista變爲:
      {0: '默認分組', 25: '青年果汁', 26: '青年果切', 22: '水果單品', -1: '推薦分組'}
    注:字典能夠以整數爲下標。
  1五、 將商品計價方式編碼轉換爲計價方式文字顯示(在base.py中)

 1 def getUnit(self,unit):
 2   if unit == 1:
 3    name =''
 4   elif unit == 2 :
 5    name =''
 6   elif unit == 3 :
 7    name =''
 8   elif unit == 4 :
 9    name ='kg'
10   elif unit == 5 :
11    name =''
12   elif unit == 6 :
13    name =''
14   elif unit == 7 :
15    name =''
16   elif unit == 8 :
17    name =''
18   elif unit == 9 :
19    name =''
20   elif unit == 10 :
21    name =''
22   elif unit == 11 :
23    name =''
24   else:
25    name =''
26   return name

【8.13 週四】

  今日任務:商品秒殺seckill
  一、 新建秒殺-後臺數據獲取:

 1 (1)先獲取到當前店鋪的group_id-group_name對照表
 2 (2)獲取當前店鋪的group_id-[(fruit_id,fruit_name),...]對照表
 3 (3)獲取當前店鋪的上架和下架的fruit_id表
 4 (4)遍歷fruit_id表,查詢fruit_id-storage對照表,只保留庫存storage不爲0的項。其中storage爲一個有兩個元素的列表,第一個元素爲浮點型,表示庫存的數目,第二個元素爲字符串,
 5 
 6 表示庫存的單位(如:斤,箱等)
 7 (5)取fruit_id-storage對照表的keys列表:fruit_id_usable_list,表示篩選出庫存不爲0的且爲上架或下架的商品id
 8 (6)遍歷fruit_id_usable_list表,從charge_type 表中查詢:
 9 查詢出fruit_id-[(price,num,unit,relate),..]對照表fruit_id_charge_type
10 說明:假如蘋果的總庫存爲storage=1000kg,蘋果的其中一種計價方式爲18元/3盒,每7盒14kg.
11 那麼這裏的各個量的值分別爲:price=18,num=3,self.getUnit(unit)='',relate=14/7=2(kg)
12 那麼當前庫存對應的該計價方式的份數爲:storage_piece=storage/relate/num = 1000/2/3 (份)
13 把storage_piece append到fruit_id-[(price,num,unit,relate),..]對照表的每一項中。
14 (7)整理傳給前端的數據:
15 ①group_id-group_name對照表
16 ②group_fruit_dict對照表中刪去庫存爲0的fruit項成爲group_usable_fruit_dict
17 ③fruit_id-storage對照表
18 ④fruit_id-[(price,num,unit,relate,storage_piece),..]對照表

  二、 js中用eval只能把python的列表轉換爲obj,不能把字典轉換成obj.
    因此若是後臺python經過get方法傳給頁面,而後js從頁面相應元素讀取的是一個字典,那麼須要先在python中把這個列表外面套一個字典才行。
  三、 jquery輸入框得到焦點事件:$("p").focus(); 或$("p").focus(fn)
    失去焦點事件:$("p").blur(); 或$("p").blur(fn)
  四、 jquery判斷正數的正則表達式:
    var reg = /^[1-9]\d*.\d*|0.\d*[1-9]\d*$/;
    console.log(reg.test('2.333'));
    輸出:true
  五、 jquery dom元素遍歷:
    jQuery中用$()方法獲取的dom元素都會返回數組 而且jQuery中有隱形迭代,有些操做你無須去刻意循環它們,例如:$("div").text("hello");那麼就會在全部的DIV中都加上hello.   若果硬要循環它們以進行某些處理 你能夠使用jQuery提供的$.each()方法,或者這樣寫:

1 $("div").each(function(){
2     //這裏幹你想幹的事情 
3     //用$(this)能夠訪問正在循環的元素 
4 });

  六、 必須設置距離如今最少五分鐘之後秒殺才能開始
  七、 jquery的return只能return出一層方法,若是有多個方法嵌套,內層return,則要設置stop-flag變量來return.
  八、 數據中少一個計價方式id.
  九、 *各列分析:

 1 1.id(該條秒殺數據項的id,id=Column(Integer,nullable=False,primary_key=True,autoincrement=True))
 2 2.activity_id(秒殺活動id,不具備惟一性,能夠有多行的activity_id相同,activity_id=Column(Integer,nullable=False);設定activity_id爲當前秒殺的店鋪id字符串加上當前秒殺活動
 3 
 4 的整形時間戳字符串)
 5 3.shop_id(該條秒殺所在的店鋪的id,shop_id=Column(Integer,nullable=False))
 6 4.start_time(秒殺開始時間,時間戳類型,start_time=Column(Integer,nullable=False))
 7 5.end_time(秒殺結束時間,時間戳類型,end_time=Column(Integer))
 8 6.continue_time(秒殺持續的時間,時間戳類型,continue_time=Column(Integer))
 9 7.fruit_id(商品id,fruit_id = Column(Integer,ForeignKey(Fruit.id,nullable=False)))
10 8.charge_type_id(當前秒殺商品的計價方式id,charge_type_id = Column(Integer,ForeignKey(ChargeType.id),nullable=False,))
11 9.former_price(原價,浮點型,former_price=Column(Float))
12 10.seckill_price(秒殺價,浮點型,計價方式與former_price相同,seckill_price=Column(Float,nullable=False))
13 11.storage_piece(當前商品剩餘庫存換算成當前計價方式的份數,取整,整形,storage_piece=Column(Integer))
14 12.activity_piece(活動庫存的份數,整形,activity_piece=Column(Integer))
15 
16 13.activity_status(當前秒殺活動的狀態,整形,activity_status = Column(TINYINT,default=1,nullable=False);取值:-1(已停用),0(已結束),1(未開始),2(進行中))
17 14.not_pick(未領取的商品的份數,默認等於當前活動庫存的份數,整形,not_pick=Column(Integer,default=0))
18 15.picked(已經領取的商品的份數,默認爲0,整形,picked=Column(Integer,default=0))
19 16.ordered(已經下單的商品的份數,默認爲0,整形,ordered=Column(Integer,default=0))
20 17.deleted(已經被從該秒殺活動中刪除的商品的份數,默認爲0,整形,deleted=Column(Integer,default=0))

  十、 js取字符串的子串:
      str = str.substr(start,lenth)(結果不包括下標爲start+lenth的字符)
  十一、 python把字符串轉換爲時間戳:
        start_time = '2015-08-12 12:34:33'
        start_time = int(time.mktime(time.strptime(start_time,'%Y-%m-%d %H:%M:%S')))
      將時間戳轉化爲localtime字符串:
        x = time.localtime(1317091800.0)
        time.strftime('%Y-%m-%d %H:%M:%S',x)
        >>2011-09-27 10:50:00

【8.14 週五】

  今日任務:商品秒殺
  一、 數據庫建表:
    

 1 (1)秒殺商品表
 2 create table seckill_goods(
 3  id int(11) not null primary key auto_increment,
 4  fruit_id int(11) not null,
 5  activity_id bigint(20) not null,
 6 
 7  charge_type_id int(11) not null,
 8  former_price float,
 9  seckill_price float not null,
10  
11  storage_piece int(11),
12  activity_piece int(11),
13 
14  not_pick int(11),
15  picked int(11) default 0,
16  ordered int(11) default 0,
17  deleted int(11) default 0,
18  status tinyint(4) default 1,
19  
20  foreign key(activity_id) references seckill_activity(id),
21  foreign key(fruit_id) references fruit(id),
22  foreign key(charge_type_id) references charge_type(id)
23 );
24 
25 (2)秒殺活動表:
26 create table seckill_activity(
27  +++id int(11) not null primary key auto_increment,
28  ---id bigint(20) not null,
29  shop_id int(11) not null,
30  start_time int(11) not null,
31  end_time int(11) not null,
32  continue_time int(11) not null,
33  
34  activity_status tinyint(4),
35 
36  foreign key(shop_id) references shop(id)
37 );
38 
39 (3)加字段:
40 marketing表中新增長一個字段,控制店鋪秒殺活動是否開啓:seckill_active=Column(TINYINT,default=1) #0:關閉  1:開啓
41 alter table marketing add column seckill_active tinyint(4) default 0;

  二、 python延時函數:time.sleep(10),延時單位:秒

1 import time
2 print "a"
3 time.sleep(5)
4 print "b"
5 time.sleep(10)

    程序會先輸出「a」,暫停5秒後再輸出「b」


【8.18 週二】

  今日任務:商品秒殺
  一、 tornado在html中給一個新變量賦值要用set:
    {% set data_item = output_data[0] %}
  二、 讓html input不可編輯的方法:
    方法1: onfocus=this.blur() 當鼠標放不上就離開焦點
        <input type="text" name="input1" value="中國" onfocus=this.blur()>
    方法2:readonly
        <input type="text" name="input1" value="中國" readonly>
        <input type="text" name="input1" value="中國" readonly="true">
    方法3: disabled
        <input type="text" name="input1" value="中國" disabled="true">
  三、 seckill_goods表新增長一個字段:
    status tinyint(4) default 1
  四、 二維碼相關外部js:
    <script src="/static/js/third/qrcode.min.js"></script>
  五、 jquery如何click,2個事件切換:
    在click外面設置一個數值變量初始爲0,每次click觸發後增長1,而後讓該變量對2取餘,不是就獲得兩個不一樣的狀態了,而後根據這個值寫函數就好了
  六、 jquery實現點擊一個div外部的任意地方隱藏這個div(假設其class爲sw-er-tip)的方法:
    假設div的外部是body,則先爲body添加點擊事件:

1 $(document).on("click",function(e){
2  if($(e.target).closest(".sw-er-tip").size()==0){
3   $(".sw-er-tip").addClass("invisible");
4  }
5 });  

    而後爲這個div添加點擊事件並中止冒泡:

1 $(document).ready(function(){
2  ...
3 )}.on("click",".spread-activity",function(e){
4  e.stopPropagation();
5  $(".sw-er-tip").addClass("invisible");
6      $(this).closest(".operate").children(".sw-er-tip").removeClass("invisible");  //operate爲sw-er-tip的外層父元素
7 });

  七、 github一次add全部文件:
    sudo git add . --ignore-removal
  八、 python把當前時間轉換爲時間戳:
    now_date=int(time.time())
  九、 當前若是有正在秒殺的活動,那麼秒殺功能不能被關閉。
  十、 Ubuntu 14.04 用戶能夠經過如下命令爲chrome安裝 Pepper Flash Player For Chromium :
      sudo apt-get install pepperflashplugin-nonfree
      sudo update-pepperflashplugin-nonfree --install

【8.19 週三】

  今日任務:商品秒殺商城端後臺
  一、 修改表結構從新建表:

 1 秒殺活動表:
 2 create table seckill_activity(
 3  id int(11) not null primary key auto_increment,
 4  shop_id int(11) not null,
 5  start_time int(11) not null,
 6  end_time int(11) not null,
 7  continue_time int(11) not null,
 8  
 9  activity_status tinyint(4),
10 
11  foreign key(shop_id) references shop(id)
12 );
13 
14 秒殺商品表
15 create table seckill_goods(
16  id int(11) not null primary key auto_increment,
17  fruit_id int(11) not null,
18  activity_id int(11) not null,
19 
20  charge_type_id int(11) not null,
21  former_price float,
22  seckill_price float not null,
23  
24  storage_piece int(11),
25  activity_piece int(11),
26 
27  not_pick int(11),
28  picked int(11) default 0,
29  ordered int(11) default 0,
30  deleted int(11) default 0,
31  status tinyint(4) default 1,
32  
33  foreign key(activity_id) references seckill_activity(id),
34  foreign key(fruit_id) references fruit(id),
35  foreign key(charge_type_id) references charge_type(id)
36 );

  二、 github忽略本地工做區刪除的文件:
     git add --ignore-removal <文件路徑路徑>',忽略本地工做區中移除的文件。
  三、 fruit表新增長字段:(一種商品只能同時參與一種活動,活動在同一商品上不能疊加)

1 activity_status = Column(TINYINT,default=0)  #0(該商品未參與任何活動),1(參與秒殺活動),2(參與限時折扣),...(等待擴展中)
2 seckill_charge_type = Column(Integer,default=0) #秒殺活動中該商品所使用的計價方式id
3 alter table fruit add column activity_status tinyint(4) default 0;
4 alter table fruit add column seckill_charge_type int(11) default 0; 

  四、 若是24小時以內沒有秒殺活動,那麼發現頁面的秒殺活動不顯示。

1 sec_fruit = self.session.query(models.Fruit).filter_by(id = fruit_id).with_lockmode('update').first()
2     sec_fruit.activity_status = 1
3     sec_fruit.seckill_charge_type = charge_type_id

  五、 秒殺活動編輯限定:

    *要在base的類中爲秒殺活動增長全局刷新函數(店鋪管理後臺,商城後臺,customer後臺)
    尚未開始的秒殺活動:全部信息均可以編輯
    正在進行中的秒殺活動:
      只能編輯活動的持續時間(並且只能比原來增長)、每種商品的活動庫存(只能比原來的增長),正在進行的秒殺活動不能添加新商品,也不能刪除現有的商品。
  六、 /seckill/(\w+)頁面數據分析:
    須要:
    [[活動id,秒殺活動開始時間,持續時間,[[商品秒殺id,商品fruit_id,商品img_url,商品名稱,商品計價方式id,商品計價方式文字,商品秒殺價省錢數,商品活動庫存],..]],...]
  七、 sqlalchemy中filter和filter_by能夠連着用,如:
    aa = self.session.query(models.Fruit).filter_by(shop_id = 4).filter(models.Fruit.id < 500).all()
    print(len(aa))


【8.20 週四】

  今日任務:商品秒殺商城端
  一、 python中的字典直接傳給js,js不能解析成對象,必須在python中爲字典外面套上一個列表才行。
  二、 sqlalchemy中預提交:
    session.flush()(和commit相似)
    若是預提交失敗則會回滾
  三、 全局實時更新店鋪秒殺活動基類方法:

 1 def update_seckill_base(self,shop_id):
 2   current_shop_id = shop_id
 3   notstart_list = self.session.query(models.SeckillActivity).filter_by(shop_id = current_shop_id,activity_status = 1).all()
 4   for item in notstart_list:
 5    now_time = int(time.time())
 6    if item.start_time <= now_time and item.end_time > now_time:
 7     item.activity_status = 2
 8     self.session.flush()
 9    elif item.start_time <= now_time and item.end_time <= now_time:
10     item.activity_status = 0
11     self.session.flush()
12   self.session.commit()
13 
14   killing_list = self.session.query(models.SeckillActivity).filter_by(shop_id = current_shop_id,activity_status = 2).all()
15   for item in killing_list:
16    now_time = int(time.time())
17    if item.end_time <= now_time:
18     item.activity_status = 0
19     self.session.flush()
20   self.session.commit()
21   return None

  四、 python字節碼
  五、 刷新數據庫店鋪秒殺活動信息
  六、 js中用hide和show方法的時候容易致使元素顯示異常,這種狀況下就要改用addClass('hidden')和removeClass('hidden')
  七、 python中字符串split,若是字符串中不包含split中的分隔符,那麼就會返回整個字符串,不會報錯。
  八、 商城商品首頁商品列表秒殺商品須要數據:
    先判斷當前店鋪當前時刻是否有秒殺活動(activity_status=2),若是有,則先返回給前臺一個秒殺活動標誌變量,秒殺img_url:
    has_seckill_activity:1,seckill_img_url:xxx(這個url只對應一個圖片,是存放在七牛上寫死的圖片連接)
    遍歷商品列表的時候,先經過fruit表的activity_status字段判斷每一個商品是不是秒殺商品(fruit表的activity_status字段對應的秒殺商品狀態碼),若是是,把返回數據的is_seckill賦值爲1
    [is_seckill:1,activity_id:xxx,seckill_goods_id:xxx,***fruit_id:xxx,charge_type_id:xxx,***img_url:xxx(只要個),***fruit_name:xxx,charge_type_text: xxx,price_dif:xxx,activity_piece:xxx]
  九、 ?要加一個限制:新建秒殺活動的時候,不能新建和當前seckill_goods表中全部activity_status=1或2(未開始秒殺和正在進行的秒殺)的fruit_id相同的商品.
?還要加一個限制:同一個秒殺活動中同一個商品只能出現一次。
  十、 在商城首頁公告表notice表中加入四個字段,用於存放活動的公告圖片url(目前url暫時是寫死的):
      http://7rf3aw.com2.z0.glb.qiniucdn.com/o_19t7mu3281ms2fnd51q17hsqqo7   團購
      http://7rf3aw.com2.z0.glb.qiniucdn.com/o_19t7mvj70f7dn221sd1pfn18l2d   折扣
      http://7rf3aw.com2.z0.glb.qiniucdn.com/o_19t7n0emj17d71ml9lftn6u1cocj  預售
      http://7rf3aw.com2.z0.glb.qiniucdn.com/o_19t7n14fh1c0s1g0hne1gu45jhp   秒殺

1 seckill_img_url = Column(String(100)) #秒殺公告背景
2 gbuy_img_url = Column(String(100)) #團購公告背景
3 dscount_img_url = Column(String(100)) #折扣公告背景
4 presell_img_url = Column(String(100)) #預售公告背景

    注:notice表中config_id就是shop_id
    字段數據添加時機:只要店鋪開啓某項活動,就把該店鋪的notice表中對應的url字段賦值爲七牛雲上的圖片url.
  十、 商城商品首頁商品列表後臺返回數據中增長判斷字段:is_activity(0:當前無活動,1:秒殺,2:xxx,...)
  十一、 ?秒殺商品表要加一個已經搶過該商品的顧客的customer_id字段,以保證同一個活動中同一件商品每一個人只能搶一份(bought_customer)
      bought_customer = Column(String(5000))
      alter table seckill_goods add column bought_customer varchar(5000);
      通過思考後,發現這種方法不太合理,並且查詢起來比較複雜,因此改變方案:新建一個customer_seckill_goods表(用戶搶購的秒殺商品表):

 1 create table customer_seckill_goods(
 2  id int(11) not null primary key auto_increment,
 3  customer_id int(11) not null,
 4  shop_id int(11) not null,
 5  seckill_goods_id int(11) not null,
 6  status tinyint(4) default 0, 
 7 
 8  foreign key(customer_id) references customer(id),
 9  foreign key(shop_id) references shop(id),
10  foreign key(seckill_goods_id) references seckill_goods(id)
11 );

  十二、 用戶搶購的秒殺商品表

1 class CustomerSeckillGoods(MapBase, _CommonApi):
2  __tablename__='customer_seckill_goods'
3  id = Column(Integer,nullable=False,primary_key=True,autoincrement=True)
4  customer_id = Column(Integer,ForeignKey(Customer.id),nullable=False)
5  shop_id = Column(Integer,ForeignKey(Shop.id),nullable=False)
6  seckill_goods_id = Column(Integer,ForeignKey(SeckillGoods.id),nullable=False)
7  status = Column(TINYINT,default=0)

  1三、 postJson能夠向別的頁面發請求,只用把url改爲其餘頁面便可。
  1四、 刪除表中的一列:
      alter table AAA drop column aName;

【8.21 週五】

  今日任務:商品秒殺商城首頁
  一、 在sqlalchemy的py文件中新建數據庫表class以後,運行系統會自動在數據庫中新建相應的表,而往已有的表中新插入字段則須要手動往數據庫中插入,並不能自動插入。
  二、 mysql自動增加的id怎麼知道剛插入的數據的id是多少?
    解決方法:
    ①先新建要插入的記錄:
    (假設Fruit表的id是自動增加的)
      record = models.Fruit(name='aaa',price=12.3)
    ②add記錄:
      self.session.add(record)
    ③flush:
      self.session.flush()
    ④insert_id = record.id
    ⑤commit:
      self.session.commit()
    ⑥再用第④步取獲得的insert_id作其餘事情。
  三、 遍歷fruit_id_usable_list表,從charge_type 表中查詢:
    查詢出fruit_id-[(price,num,unit,relate),..]對照表fruit_id_charge_type
    說明:假如蘋果的總庫存爲storage=1000kg,蘋果的其中一種計價方式爲18元/3盒,每7盒14kg.
         那麼這裏的各個量的值分別爲:price=18,num=3,self.getUnit(unit)='盒',relate=14/7=2(kg)
       那麼當前庫存對應的該計價方式的份數爲:storage_piece=storage/relate/num = 1000/2/3 (份)
    把storage_piece append到fruit_id-[(price,num,unit,relate),..]對照表的每一項中。
  四、 在處理秒殺商品的計價方式的時候遇到了較複雜的問題,討論了一下午:
    若是不將秒殺商品的計價方式做爲一種新的計價方式插入計價方式表中,那麼在生成訂單和統計數據的時候將會遇到不方便和數據不完整的問題;若是將秒殺商品的計價方式做爲一種新的計價方式插入計價方式表中,那麼不少和計價方式相關的地方都要相應的改變,工做量很大。
最後權衡利弊以後,決定這樣處理:
    在計價方式表中新增一個字段activity_type = Column(TINYINT,default=0),用於表示當前這條計價方式對應的活動類型,默認值是0,表示當前計價方式不屬於任何活動,其餘值:1(秒殺活動新建的計價方式),2(限時折扣活動新建的計價方式),...
    而後在每次新建或者編輯秒殺商品信息後,都向計價方式表中插入該秒殺商品對應的計價方式記錄,並把生成的計價方式id插入到秒殺商品表中。在搶購和下單的時候,都以這個計價方式爲依據進行處理。
    最後再在全部有對計價方式進行遍歷的地方判斷計價方式的activity_type,篩選出來須要的計價方式。
  五、 python列表刪除符合條件的元素:

 1 >>> a = [1,2,3,4]
 2 >>> list(filter(lambda e:e!=1,a))
 3 [2, 3, 4]
 4 >>> a
 5 [1, 2, 3, 4]
 6 
 7 >>> a = [{'a':111,'b':345},{'a':23,'b':3}]
 8 >>> a
 9 [{'b': 345, 'a': 111}, {'b': 3, 'a': 23}]
10 >>> a = list(filter(lambda item:item['a'] != 111,a))
11 >>> a
12 [{'b': 3, 'a': 23}]
13 
14 或者:
15 a = [e for e in a if e!=1]
16 a = [e for e in a if e['a'] != 111]

  六、 jquery中each方法中發ajax請求時候,可能會因爲異步的緣由致使先執行後面的代碼再執行請求致使邏輯錯亂,爲了不這個問題,須要在發ajax請求以前關閉異步:

1 $.ajaxSetup({
2  async : false
3 });

  七、 linux截屏軟件:
    sudo apt-get install scrot
    而後命令行輸入:scrot -s能夠用鼠標選區而後保存截圖到當前目錄。 

【8.24 週一】
  一、 今日任務:商品秒殺商城端支付環節
  二、 要加一個限制:同一個秒殺活動中不能存在兩種相同的商品。
  三、 jquery中遍歷某個類的全部元素的兩種方法:

1for(var i=0; i<$('.aaa').size;i++){
2  var $this = $('.aaa').eq(i);
3  function($this){
4   ... 
5  }
6 }
1 ②$('.aaa').each(function(){
2  ...
3 }

    注:用each方法遍歷若是each中有ajax函數,那麼要在執行ajax函數前關閉異步,不然會致使執行時候邏輯錯亂的問題。
  四、 關閉ajax異步:

1 $.ajaxSetup({
2  async : false
3 });

  五、 對於charge_type表的分析:

1 price unit num unit_num active market_price select_num relate
2 50      8    2      7        1         48            19         2.714
3 轉換成'每份'的計價方式:
4 50      3    1     7/2       1         48            19    19/(7/2)(=2.714*2)

  六、 seckill_goods表加一個字段:
    seckill_charge_type_id = Column(Integer,ForeignKey(ChargeType.id),nullable=False)  #當前秒殺商品的計價方式id
    alter table seckill_goods add column seckill_charge_type_id int(11) not null references

    charge_type(id);
  七、 charge_type表新增長一個字段:
    activity_type = activity_type = Column(TINYINT,default=0) #0:正常計價方式,未參與任何活動;1:秒殺活動計價方式;2:限時折扣活動計價方式
    alter table charge_type add column activity_type tinyint(4) default 0;
    注:每次新建或編輯秒殺活動後都往charge_type表中插入秒殺活動新建的計價方式。
  八、 m-admin/js/util.js裏面有各類工具方法。
  九、 商品若是正在參加秒殺活動,那麼不容許下架(在商品下架接口中要加以判斷)

 1    end_charge_type = [x for x in charge_types if x.activity_type == -1]
 2    end_charge_type_id = []
 3    for item in end_charge_type:
 4     end_charge_type_id.append(item.id)
 5    seckill_goods_list = self.session.query
 6 
 7 (models.SeckillGoods).filter(models.SeckillGoods.seckill_charge_type_id.in_
 8 
 9 (end_charge_type_id)).with_lockmode('update').all()
10    for item in seckill_goods_list:
11     item.picked -= 1
12     item.not_pick += 1
13    self.session.commit()

  十、 店鋪商品管理中,商品詳細信息是在base.py的getGoodsData方法中查詢到的。

  十一、 用戶在購物車中刪除秒殺商品後要有相應的響應。

  十二、 mysqldump -uroot -psenguo senguocc > senguocc2015-8-24.sql

【8.25 週二】
  今日任務:商品秒殺商城端支付環節
  一、 今天遇到好幾回python3的錯誤:'段錯誤(核心已轉儲)'
  二、 seckill_goods表的activity_piece,not_pick,picked,ordered四個字段之間的關係:
    商品首頁和秒殺的發現頁面顯示的秒殺商品的庫存爲activity_piece,只有當一個商品被下單成功後該庫存才減去1;當一個商品被用戶放到購物車裏時,not_pick減1,picked加1,另外兩個不變;當一個正在參與秒殺的商品被用戶從購物車裏刪除時,not_pick加1,picked減1;當一個秒殺商品被用戶下單成功後,activity_piece減1.
  三、 加載商品首頁時遇到以下警告,加載速度很是慢,達到一分鐘多:

 1 /usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/default_comparator.py:153: SAWarning: 
 2 
 3 The IN-predicate on "charge_type.id" was invoked with an empty sequence. This results in a 
 4 
 5 contradiction, which nonetheless can be expensive to evaluate.  Consider alternative 
 6 
 7 strategies for improved performance.
 8   'strategies for improved performance.' % expr)
 9 /usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/default_comparator.py:153: SAWarning: 
10 
11 The IN-predicate on "seckill_goods.seckill_charge_type_id" was invoked with an empty 
12 
13 sequence. This results in a contradiction, which nonetheless can be expensive to evaluate.  
14 
15 Consider alternative strategies for improved performance.
16   'strategies for improved performance.' % expr)
17 [I 150825 18:39:40 web:1811] 200 GET /jyjfruit (127.0.0.1) 73.69ms
18 /usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/default_comparator.py:153: SAWarning: 
19 
20 The IN-predicate on "seckill_goods.activity_id" was invoked with an empty sequence. This 
21 
22 results in a contradiction, which nonetheless can be expensive to evaluate.  Consider 
23 
24 alternative strategies for improved performance.

    後來從新導入數據庫,換了一家店鋪進行測試,問題解決。
  三、 新建秒殺時要判斷各個商品是否在同一時間段的其餘商品已經存在,若是存在,則不能進行新建。

【8.26 週三】
  今日任務:商品秒殺商城端支付環節
  一、 點擊購物車的'提交訂單'後,js向後臺發post請求的參數中,fruits參數的形式爲:
     {'12668': 2, '12641': 3, '12645': 1},表示計價方式和數量的鍵值對字典;
    在該post請求的一開始要更新秒殺數據,而後設置一個overdue變量,初始化爲0,而後遍歷fruits列表的計價方式判斷有沒有商品的活動過時,若是有商品的活動過則置overdue爲1,直接self.send_success(overdue=overdue),前臺根據overdue的值重定向到當前購物車頁面,並給用戶發出提示,刷新購物車

頁面,從新進行處理。
  二、 問題:編輯秒殺活動時,在斷定選擇商品是否與該時間段其餘活動的商品重複時,會出現'與當前活動秒殺商品重複'的錯誤。
  三、 對於餘額支付和貨到付款的訂單,商家刪除訂單後,會恢復庫存;在線支付的還不能刪除。
  四、 在商城端顯示秒殺商品的時候,要先斷定該秒殺商品的ordered值是否等於activity_piece,若是相等,則代表已經被搶光了,不予顯示。
  五、 在線支付是有15分鐘的付款時間的,若是15分鐘內未付款,那麼訂單將會自動取消,返還庫存。
    對於秒殺活動的在線支付這樣處理:
      給用戶15分鐘的在線支付時間,在這期間只要完成在線支付便可,不用管活動是否到期。15分鐘之後自動取消訂單。
  六、 秒殺商品和限時折扣商品的去重問題:同一時間段內同一商品不能參加不一樣的活動,也不能參加同一種活動在同一時間段內的不一樣場次。
由於限時折扣涉及到週期性活動的問題,因此去重比較複雜。並且在與循環時間比較的時候還要注意python的時區問題。
    *思路:在全局基類中爲秒殺活動和限時折扣活動分別寫judge_seckill和judge_discount方法,其餘活動能夠調用這兩個方法判斷其餘活動將要新建的商品是否在這兩個活動裏面,參數基本形式以下:def judge_seckill(self,fruit_id,time_way,start_time,end_time,f_time,t_time,weeks)

    *參數分析:其中time_way表示參數時間的形式,time_way=0表示參數時間爲start_time和end_time,非週期時間,此時忽略f_time,t_time,weeks三個參數;若time_way=1則表示參數時間爲f_time和t_time以及weeks,這爲週期時間,此時忽略start_time和end_time兩個參數。其中weeks爲一個整型列表,元素爲表明周幾的整數(取值1-7),f_time表示天天的開始時間(是一個整型的秒數,介於0到24小時之間),t_time表示天天的結束時間(是一個整型的秒數,介於0到24小時之間)返回值:True(傳入參數fruit_id對應的商品和當前已經創建的秒殺活動時間上無衝突);False(傳入參數fruit_id對應的商品和當前已經創建的秒殺活動時間上有衝突)
  七、 獲取星期數:

1 >>> x = time.localtime(1317091800.0)
2 >>> time.strftime('%w',x)
3 '2'
4 >>> time.strftime('%Y-%m-%d %H:%M:%S',x)
5 '2011-09-27 10:50:00'

 

【8.27 週四】
  今日任務:已經完成商品秒殺從商城端到店鋪後臺端的所有功能,接下來的兩天主要是全方位debug.
  一、 python延時執行函數的方法:
    work = Timer(60*15,func,(param1,param2,))
    work.start()
  二、 爲order表新增字段activity_type,類型爲鍵值對字符串,鍵是計價方式,值是計價方式對應的活動名稱,用於存儲該訂單中每種計價方式id對應的水果參與的活動名稱,若是值爲空字符串,則表示未參與任何活動;若是值爲非空,則表示參與了值字符串所表示的活動。
    alter table senguocc.order add column fruit_activity varchar(1000);
    fruit_activity = Column(String(1000))
    後來考慮不用新加字段,只用利用現有的fruits字段便可。
  三、 在訂單詳情顯示中,每種商品名稱前都添加參與的活動名稱,若是未參與任何活動則不添加,相似這樣:
    {% if 'activity_name' in list(fruits[key].keys()) and fruits[key]['activity_name'] %}({{fruits[key]['activity_name']}}){% end %}{{fruits[key]['fruit_name']}}
  四、 access_token表存微信的認證信息,用於發模板消息。若是發現發送失敗,那麼先清空這個表再試試。
    delete from access_token;
【8.28】

  今日任務:商品秒殺全方位debug.
  森果實習最後一天
  一、 爲全部包含折扣商品的訂單的fruits字段添加折扣數(0~1之間),非折扣商品的折扣數爲1,顯示訂

單商品詳情的時候折扣商品要顯示原價乘上折扣數的價格。

 1 discount_rate
 2 {% if 'discount_rate' in list(fruits[key].keys()) %}{{round(float(price1)*fruits[key]
 3 
 4 ['discount_rate']*fruits[key]['num'], 2)}}{% else %}{{round(float(price1)*fruits[key]
 5 
 6 ['num'], 2)}}{% end %}
 7 
 8 {% if 'discount_rate' in list(fruits[charge_type.id].keys()) %}{{round(float(price1)
 9 
10 *fruits[charge_type.id]['discount_rate']*fruits[charge_type.id]['num'], 2)}}{% else %}
11 
12 {{round(float(price1)*fruits[charge_type.id]['num'], 2)}}{% end %}

  二、 artTemplate中if語句用法:{{ if a == 1 }}...{{else}}...{{/if}},和tornado中不一樣。
  三、 測試服務器測試報告:
    1.新建秒殺頁面商品信息卡的overflow:auto屬性丟失,要加上。(ok)
    2.店鋪後臺商品管理添加計價方式後,會將以前的計價方式所有成對顯示。(ok)
    解決:admin.py 2666行q_charge = self.session.query(models.ChargeType).filter_by(id=charge_type['id']).filter(models.ChargeType.activity_type.in_([0,-2]))一句中_in後面少了小括號,加上便可.
    3.代碼推到線上的時候,要改動的地方:
    ①店鋪後臺秒殺管理的'點擊查看使用教程'的連接要改爲bbs中正確的秒殺教程url連接。
    ②店鋪後臺秒殺管理的'推廣連接'要改爲線上的url.(ok)

******************************************************************************************************************end

  至此,爲期三個月的森果實習結束,感覺頗多,成長頗多,感覺及總結將會陸續總結在其餘博文中。感謝森果。

相關文章
相關標籤/搜索