登陸與注冊注冊功能: 流程: 填寫用戶名,郵箱,獲取郵箱驗證碼,填入密碼 單擊<下一步>按鈕,完成注冊! 1.獲取郵箱驗證碼(具體步驟分析): 1.利用ajax 往后臺傳入郵箱, 2.后臺表單驗證,郵箱填寫是否正確, => 成功,則繼續(xù)3, => 錯誤,寫入錯誤信息,頁面輸出錯誤提示! 3.查詢sendcode 數(shù)據(jù)庫表,查詢該郵箱是否是第一次發(fā)送驗證碼 => 第一次發(fā)送: 數(shù)據(jù)表中插入記錄 (郵箱,發(fā)送次數(shù)1,郵箱驗證碼,狀態(tài)1,有效時間:當前時間-1小時) => 否則: 從數(shù)據(jù)表中查詢出該郵箱驗證碼發(fā)送次數(shù), => 如果 >5 則,再判斷上次發(fā)送時間+1小時 是否大于當前時間! => 大于當前時間,則發(fā)送驗證碼,修改數(shù)據(jù)表記錄 (發(fā)送次數(shù)+1,郵箱驗證碼,有效時間) => 小于當前時間,則為多次惡意發(fā)送,不操作,寫入錯誤信息,需要等待1小時, => 如果<5 則直接發(fā)送驗證碼,修改數(shù)據(jù)表記錄 (發(fā)送次數(shù)+1,郵箱驗證碼,有效時間) 4.json信息返回。 ![]() ![]() ![]() 2.驗證碼發(fā)送過程: 頁面倒計時 原理:設計計時器,每1秒修改1次text值, 時間小于0時,取消計時器 ![]() 3.賬號注冊 1.JQ獲取前臺輸入表單內(nèi)容 2.ajax傳輸給后臺,建立表單驗證 => 正確,繼續(xù)3 => 錯誤,返回錯誤信息,頁面顯示錯誤信息 3.數(shù)據(jù)庫中查詢用戶郵箱是否存在 => 不存在,插入數(shù)據(jù)庫,繼續(xù)4 => 存在,返回錯誤信息,頁面顯示 4.注冊賬號完成,寫入session,注冊完成頁面刷新實現(xiàn)自動登錄 ![]() ![]() 表單錯誤時,頁面信息提示(效果圖): 登錄功能: 原理:與注冊功能類似 1.圖片驗證碼:點擊驗證碼,自動更改 驗證碼為后臺生成的圖片,每點擊一次,src地址后面 多加?實現(xiàn)切換 <div class="inp-block"> <input type="text" name="phoneregister" placeholder="請輸入驗證碼" id="u-code" class="phonenum" autocomplete="off"/> <img src="/check_code" onclick='ChangeCode();' id='imgCode' class="codeimg"> </div> ![]() ![]() ![]() ![]() ![]() 表單驗證設計思想: 無論表單通過form形式,或者ajax形式,發(fā)送數(shù)據(jù)給后端,我們都要先通過:某些規(guī)則進行過濾和驗證,再對其進行數(shù)據(jù)的插入,修改等操作 實現(xiàn)思路:1,有form表單數(shù)據(jù)來臨時,初始化一個表單類,傳入self; 2,自動獲取form上數(shù)據(jù)字段,self.get_arguments(name),name與前端input標簽的name名字一一對應; 3,通過表單類,調(diào)用檢測方法 check_value(), 4,如果form表單數(shù)據(jù),符合自定義的規(guī)則,以字典形式返回數(shù)據(jù),{ ‘前端input的name值’:‘input的value值’ } =》 存儲在表單類的 self._value_dict 中 5,如果form表單數(shù)據(jù),不符合自定義的規(guī)則,以字典形式返回錯誤信息,{ ‘前端input的name值’:‘錯誤信息’ } =》 存儲在表單類的 self._error_dict 中
1. 定義一個表單類 LoginForm ,__init__方法中對象名為 前端input標簽的name值 required 是否可以為空值, error_dict 定義錯誤信息輸出內(nèi)容 class LoginForm(BaseForm): def __init__(self): self.username = UsernameField(required=True,error_dict={'required':'用戶名不能為空' , 'valid':'用戶名錯誤'}) self.password = PasswordField(required=True,error_dict={'required':'密碼不能為空' , 'valid':'用戶名或密碼錯誤'}) self.code = CodeField(required=True,error_dict={'required':'驗證碼不能為空' , 'valid':'驗證碼錯誤'}) self.remember = CheckBoxField(required=False,error_dict={'valid':'格式錯誤'}) super(LoginForm, self).__init__() 2. 繼承BaseForm類,該類初始化了,當前Form表單共用的最后返回數(shù)據(jù)和錯誤信息的字典對象 class BaseForm(): def __init__(self): self._value_dict = {} self._error_dict = {} self._valid_status = True def check_value(self): .... check_value() 執(zhí)行獲取前端輸入的數(shù)據(jù),self.get_argument(xxxx) 并且根據(jù)每個input標簽定義的規(guī)則去驗證數(shù)據(jù)的正確性 (上文的UsernameField,PasswordField..等) 通過self.__dict__循環(huán)獲取LoginForm的成員對象,調(diào)用Field的validate()方法,驗證Form表單中每一個的值。驗證正確,信息存儲在self._value_dict 中, 錯誤信息存儲在self._error_dict 中 def check_value(self,handler): for key,regular in self.__dict__.items(): input_value = handler.get_argument(key,None) regular.validate(key,input_value) if regular.is_valid: self._value_dict[key] = regular.value else: self._error_dict[key] = regular.error ![]() 3. Field 自定義的規(guī)則類 為前端input標簽,定義不同的驗證規(guī)則(正則表達式),驗證用戶輸入的數(shù)據(jù) class PasswordField(Field): REGULAR = "[0-9 | A-Z | a-z]{6,16}" def __init__(self,required=True,error_dict=None): self.error_dict = {} #錯誤信息 if error_dict: self.error_dict.update(error_dict) #用戶自定義的錯誤信息 self.required = required super(PasswordField, self).__init__() 繼承父類Field,初始化存儲信息的成員 class Field: def __init__(self): self.is_valid = False # 驗證規(guī)則是否通過,默認False self.name = None self.value = None # 獲取的前端input值 self.error = None def validate(self, name, input_value): ... 執(zhí)行validate()方法, 1.先判斷該值是否允許為空?, => 可以為空,驗證通過,self.value = input輸入值 => 不可以為空, 判斷 input輸入值 是否為空? => input輸入值為空,self.error = 定義的錯誤信息(required) => 不為空,繼續(xù)正則表達式判斷,re.match(REGULAR,input_value) => 正則通過,self.value = input輸入值, self.is_valid = True => 正則不通過, self.error = 定義的錯誤信息(valid) ![]() 自定義的Field 供參考: ![]() ![]() ![]() Session設計思想: 利用Cookie 自定義一個Session來存儲每個用戶信息 實現(xiàn)思路: 1. Session信息設計成一個大字典,key對應用戶唯一識別加密串,value對應空字典{}存儲用戶信息,存放在服務端上。 2. 為用戶請求生成一個唯一加密串,寫入到Cookie信息中,Session_id = 加密串,用于區(qū)分每一個用戶。 3. 當用戶請求到來時,獲取該請求的Cookie信息,判斷是否存在Session_id(用戶唯一識別加密串)? => 如果存在Session_id 并且在 Session大字典中找到相同的 key,記錄Session_id => 其他情況下一律,生成加密串,寫入到Cookie中,同時寫入到 Session大字典中 class CacheSession(): session_id = "__balabala__" # Cookie中為Session存儲的名字 session_container = {} # Session大字典 def __init__(self,handler): self.handler = handler client_random_str = self.handler.get_cookie(CacheSession.session_id,None) if client_random_str and client_random_str in CacheSession.session_container: self.random_str = client_random_str else: self.random_str = self.__container__random__str() CacheSession.session_container[self.random_str] = {} expires_time = time.time() + config.SESSION_EXPIRES self.handler.set_cookie(CacheSession.session_id, self.random_str, expires=expires_time) # 方便后續(xù)定義過期時間! def __container__random__str(self): # 生成加密串 hash = hashlib.md5() hash.update(bytes(str(time.time()), encoding='utf-8')) random_str = hash.hexdigest() return random_str 利用方法:1. 當用戶請求到達每個Handler時,我們都需要先實例化一個CacheSession(), 2. 此時我們可以定義一個父類BaseHandler,initialize() 方法中寫入要執(zhí)行代碼, import tornado.web form session import SessionFactory class BaseHandler(tornado.web.RequestHandler): def initialize(self): self.session = SessionFactory.get_session_obj(self) 可以看到,我們在session.py中定義了一個新的類SessionFactory,用來選擇合適的方法,初始化Session, 該類通過讀取配置文件config中的SESSION_TYPE選擇適合的Session類進行初始化,并且返回一個Session對象,該對象最終存儲在 self.session中。 class SessionFactory(): @staticmethod def get_session_obj(handler): if config.SESSION_TYPE == 'cache': obj = CacheSession(handler) elif config.SESSION_TYPE == 'memcached': obj = MemcachedSession(handler) elif config.SESSION_TYPE == 'redis': obj = RedisSession(handler) return obj Handler 中使用Session class LoginUserHandler(BaseHandler): def post(self, *args, **kwargs): self.session['is_login'] = 1 self.write('ok') 1.緩存Session ![]() 2.memcache session ![]() 3.radis session ![]() 需要注意的是:__setitem__,__getitem__和__delitem__ 使用類似字典方式設置,訪問,刪除成員。 在緩存Session 中,他們的使用方法與字典差別不大。 在memcache 中,鍵值對key,value 都是以字符串的形式存儲的, 在設置值前需要將value值通過json轉(zhuǎn)換成字典形式,再對字典進行操作,操作完畢后,用json轉(zhuǎn)換回字符串,存儲回原來位置! 在redis 中,選用hash操作進行存儲,如果待存儲的value值為字典,需要先把value通過json轉(zhuǎn)換成字符串,再存儲在redis中, 獲取某個key的value值時,由于hash中value是以bytes存儲,需要先轉(zhuǎn)換成str類型,再判斷該key存儲的是字典,還是普通字符串 Session所有的完整代碼: ![]() ![]() ![]() 分頁設計思路:與Tornado篇分頁同理 前端: ![]() 后臺Url配置:
后臺Handle: class IndexHandler(BaseHandler): def get(self, page): query = QueryContent() page_obj = pager.Pagiantion(page, all_item=query.queryCounts(), per_num=5) #page 當前頁碼 , all_item 總數(shù)據(jù)條數(shù), per_num 每頁顯示條數(shù) str_page = page_obj.page_str('/index/') self.render("index.html", str_page=str_page ) Pagiantion 分頁類: ![]() ![]() 頁面登陸驗證(裝飾器方式實現(xiàn))1.普通登陸驗證
2.ajax提交數(shù)據(jù)的登陸驗證
文件上傳為了美觀 , 文件上傳標簽一半由兩部分組成 file標簽和 button標簽
file標簽會設置 透明度 和 定位在button上 , 綁定onchange事件 .up-block{ position: relative; } .file-path{ position: absolute; width: ..px; height: ..px; font-size: ..px; opacity: 0; z-index: 10; } 圖片上傳后,展示在上傳頁面: 方法一:利用iframe實現(xiàn) ![]() 抽屜網(wǎng)實現(xiàn),完整代碼: ![]() ![]() ![]() 方法二:ajax實現(xiàn) 通過Ajax的FormData對象來實現(xiàn)。詳情參考ajax篇
|
|
來自: highoo > 《數(shù)據(jù)分析》