democss
視圖html
from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import * from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def index(request): ''' 批量導入數據: Booklist=[] for i in range(100): Booklist.append(Book(title="book"+str(i),price=30+i*i)) Book.objects.bulk_create(Booklist) ''' ''' 分頁器的使用: book_list=Book.objects.all() paginator = Paginator(book_list, 10) print("count:",paginator.count) #數據總數 print("num_pages",paginator.num_pages) #總頁數 print("page_range",paginator.page_range) #頁碼的列表 page1=paginator.page(1) #第1頁的page對象 for i in page1: #遍歷第1頁的全部數據對象 print(i) print(page1.object_list) #第1頁的全部數據 page2=paginator.page(2) print(page2.has_next()) #是否有下一頁 print(page2.next_page_number()) #下一頁的頁碼 print(page2.has_previous()) #是否有上一頁 print(page2.previous_page_number()) #上一頁的頁碼 # 拋錯 #page=paginator.page(12) # error:EmptyPage #page=paginator.page("z") # error:PageNotAnInteger ''' book_list=Book.objects.all() paginator = Paginator(book_list, 10) page = request.GET.get('page',1) currentPage=int(page) try: print(page) book_list = paginator.page(page) except PageNotAnInteger: book_list = paginator.page(1) except EmptyPage: book_list = paginator.page(paginator.num_pages) return render(request,"index.html",{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})
模板python
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <div class="container"> <h4>分頁器</h4> <ul> {% for book in book_list %} <li>{{ book.title }} -----{{ book.price }}</li> {% endfor %} </ul> <ul class="pagination" id="pager"> {% if book_list.has_previous %} <li class="previous"><a href="/index/?page={{ book_list.previous_page_number }}">上一頁</a></li> {% else %} <li class="previous disabled"><a href="#">上一頁</a></li> {% endif %} {% for num in paginator.page_range %} {% if num == currentPage %} <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li> {% else %} <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li> {% endif %} {% endfor %} {% if book_list.has_next %} <li class="next"><a href="/index/?page={{ book_list.next_page_number }}">下一頁</a></li> {% else %} <li class="next disabled"><a href="#">下一頁</a></li> {% endif %} </ul> </div> </body> </html>
進階限制所顯示的分頁數量web
1 def index(request): 2 3 4 book_list=Book.objects.all() 5 6 paginator = Paginator(book_list, 15) 7 page = request.GET.get('page',1) 8 currentPage=int(page) 9 10 # 若是頁數十分多時,換另一種顯示方式 11 if paginator.num_pages>11: 12 13 if currentPage-5<1: 14 pageRange=range(1,11) 15 elif currentPage+5>paginator.num_pages: 16 pageRange=range(currentPage-5,paginator.num_pages+1) 17 18 else: 19 pageRange=range(currentPage-5,currentPage+5) 20 21 else: 22 pageRange=paginator.page_range 23 24 25 try: 26 print(page) 27 book_list = paginator.page(page) 28 except PageNotAnInteger: 29 book_list = paginator.page(1) 30 except EmptyPage: 31 book_list = paginator.page(paginator.num_pages) 32 33 34 return render(request,"index.html",locals())
自定義分頁組件算法
import copy """ 自定義分頁 """ class Pagination(object): def __init__(self, current_page_num, all_count, request, per_page_num=10, max_page_num=11): """ 封裝分頁相關數據 :param current_page_num: 當前頁碼 :param all_count: 數據總數 :param per_page_num: 每頁顯示的數據條數 :param max_page_num: 最大顯示的頁數 """ # 捕捉異常頁碼,異常則顯示第一頁 try: current_page_num = int(current_page_num) except Exception as e: current_page_num = 1 if current_page_num < 1: current_page_num = 1 if current_page_num > all_count/per_page_num: all_pager, tmp = divmod(all_count, per_page_num) if tmp: current_page_num = all_pager+1 else: current_page_num = all_pager self.current_page_num = current_page_num self.all_count = all_count self.per_page_num = per_page_num self.max_page_num = max_page_num # 計算總頁數 all_pager, tmp = divmod(all_count, per_page_num) if tmp: all_pager += 1 self.all_pager = all_pager # 計算最多顯示頁數的一半,爲了頁數過多時,只實現必定的數量的實現作準備 self.max_page_num_half = int((max_page_num-1)/2) # 保存搜索條件 獲取{"a":"1","b":"2"} self.params = copy.deepcopy(request.GET) # 計算當前頁所顯示數據的起始索引 @property def start(self): return (self.current_page_num - 1)*self.per_page_num # 計算當前頁所顯示數據的結束索引 @property def end(self): return self.current_page_num * self.per_page_num # 自定義分頁的邏輯函數 def page_html(self): # 總頁碼數 < 最大顯示頁碼數,即所有顯示 if self.all_pager < self.max_page_num: page_start = 1 page_end = self.all_pager + 1 # 總頁碼數 > 最大顯示頁碼數,即顯示最大頁碼數 else: # 當前頁 <= 最多顯示頁數的一半,即顯示前max_page_num條 if self.current_page_num <= self.max_page_num_half: page_start = 1 page_end = self.max_page_num + 1 # 當前頁 > 最多顯示頁數的一半 else: # 顯示最後的max_page_num條 if (self.current_page_num + self.max_page_num_half) > self.all_pager: page_start = self.all_pager - self.max_page_num_half + 1 page_end = self.all_pager + 1 # 顯示中間的max_page_num條 else: page_start = self.current_page_num - self.max_page_num_half page_end = self.current_page_num + self.max_page_num_half + 1 # 上一頁 首頁 頁碼 尾頁 下一頁 page_html_list = [] # 當前頁爲第一頁時不可點擊,當前頁大於第一頁時點擊時當前頁碼-1 if self.current_page_num <= 1: prev_page = '<li class="disabled paginate_button"><a href="#">上一頁</a></li>' else: self.params['page'] = self.current_page_num - 1 prev_page = '<li class="paginate_button"><a href="?%s">上一頁</a></li>' % (self.params.urlencode(),) page_html_list.append(prev_page) # 首頁 first_page = '<li class="paginate_button"><a href="?page=%s">首頁</a></li>' % (1,) page_html_list.append(first_page) # 頁碼 for i in range(page_start, page_end): self.params['page'] = i if i == self.current_page_num: temp = '<li class="active paginate_button"><a href="%s">%s</a></li>' % (self.params.urlencode(), i) else: temp = '<li class="paginate_button"><a href="?%s">%s</a></li>' % (self.params.urlencode(), i) page_html_list.append(temp) # 尾頁 last_page = '<li class="paginate_button"><a href="?page=%s">尾頁</a></li>' % (self.all_pager,) page_html_list.append(last_page) # 當前頁爲尾頁時不可點擊,當前頁小於尾頁時點擊時當前頁碼+1 if self.current_page_num >= self.all_pager: next_page = '<li class="disabled paginate_button"><a href="#">下一頁</a></li>' else: self.params['page'] = self.current_page_num + 1 next_page = '<li class="paginate_button"><a href="?%s">下一頁</a></li>' % (self.params.urlencode(),) page_html_list.append(next_page) return ''.join(page_html_list)
視圖函數中的使用數據庫
# 分頁 注意分頁應用了切片,可是一旦切片就不能再filter current_page_num = request.GET.get("page") pagination = Pagination( current_page_num, customer_list.count(), request, per_page_num=5) customer_list = customer_list[pagination.start:pagination.end]
模板中的使用django
{{ pagination.page_html|safe }}
頁碼渲染
表單渲染時使用切片後的數據,便可實現分頁
咱們知道HTTP協議是無狀態協議,也就是說每一個請求都是獨立的!沒法記錄前一次請求的狀態。但HTTP協議中可使用Cookie來完成會話跟蹤!在Web開發中,使用session來完成會話跟蹤,session底層依賴Cookie技術。 bootstrap
其實Cookie是key-value結構,相似於一個python中的字典。隨着服務器端的響應發送給客戶端瀏覽器。而後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。 Cookie是由服務器建立,而後經過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪一個服務器的Cookie)。當客戶端向服務器發出請求時會把全部這個服務器Cookie包含在請求中發送給服務器,這樣服務器就能夠識別客戶端了!後端
Cookie是經過HTTP請求和響應頭在客戶端和服務器端傳遞的: 瀏覽器
若是服務器端發送重複的Cookie那麼會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie: a=AA,那麼客戶端只留下一個Cookie,即:a=AA。
設置cookie:
rep = HttpResponse(...) 或 rep = render(request, ...) 或 rep = redirect() rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密鹽',...)
獲取cookie:
request.COOKIES
刪除cookie:
response.delete_cookie("cookie_key",path="/",domain=name)
Session是服務器端技術,利用這個技術,服務器在運行時能夠 爲每個用戶的瀏覽器建立一個其獨享的session對象,因爲 session爲用戶瀏覽器獨享,因此用戶在訪問服務器的web資源時 ,能夠把各自的數據放在各自的session中,當用戶再去訪問該服務器中的其它web資源時,其它web資源再從用戶各自的session中 取出數據爲用戶服務。
1、設置Sessions值 request.session['session_name'] ="admin" 2、獲取Sessions值 session_name = request.session["session_name"] 3、刪除Sessions值 del request.session["session_name"] 4、flush() 刪除當前的會話數據並刪除會話的Cookie。 這用於確保前面的會話數據不能夠再次被用戶的瀏覽器訪問
五、get(key, default=None) fav_color = request.session.get('fav_color', 'red') 6、pop(key) fav_color = request.session.pop('fav_color') 7、keys() 8、items() 9、setdefault() 用戶session的隨機字符串 request.session.session_key # 將全部Session失效日期小於當前日期的數據刪除 request.session.clear_expired() # 檢查 用戶session的隨機字符串 在數據庫中是否 request.session.exists("session_key") # 刪除當前用戶的全部Session數據 request.session.delete("session_key") request.session.set_expiry(value) * 若是value是個整數,session會在些秒數後失效。 * 若是value是個datatime或timedelta,session就會在這個時間後失效。 * 若是value是0,用戶關閉瀏覽器session就會失效。 * 若是value是None,session會依賴全局session失效策略。 補充語法
Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。 a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認) SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie(默認) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否關閉瀏覽器使得Session過時(默認) SESSION_SAVE_EVERY_REQUEST = False # 是否每次請求都保存Session,默認修改以後才保存(默認)
from django.contrib import auth
django.contrib.auth中提供了許多方法,這裏主要介紹其中的三個:
提供了用戶認證,即驗證用戶名以及密碼是否正確,通常須要username password兩個關鍵字參數
若是認證信息有效,會返回一個 User 對象。authenticate()會在User 對象上設置一個屬性標識那種認證後端認證了該用戶,且該信息在後面的登陸過程當中是須要的。當咱們試圖登錄一個從數據庫中直接取出來不通過authenticate()的User對象會報錯的!!
user = authenticate(username='someone',password='somepassword')
該函數接受一個HttpRequest對象,以及一個認證了的User對象 此函數使用django的session框架給某個已認證的用戶附加上session id等信息。
from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: login(request, user) # Redirect to a success page. ... else: # Return an 'invalid login' error message. ...
from django.contrib.auth import logout def logout_view(request): logout(request) # Redirect to a success page.
該函數接受一個HttpRequest對象,無返回值。當調用該函數時,當前請求的session信息會所有清除。該用戶即便沒有登陸,使用該函數也不會報錯。
User 對象屬性:username, password(必填項)password用哈希算法保存到數據庫
若是是真正的user 對象,返回值恆爲True.用於檢查用戶是否已經經過了驗證.
經過認證並不意味着用戶擁有任何權限,甚至也不檢查該用戶是否處於激活狀態,這只是代表用戶成功的經過了驗證,這個方法很重要,在後臺用request.
user.is_authenticated()判斷用戶是否已經登陸,若是true則能夠向前臺展現request.user.name
要求:
1 用戶登錄後才能訪問某些頁面,
2 若是用戶沒有登陸就訪問該頁面的話直接跳到登陸頁面
3 用戶在跳轉的登錄界面中完成登錄後,自動訪問跳轉到以前訪問的地址
方法1:
def my_view(request): if not request.user.is_authenticated(): return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
方法2:
django已經爲咱們設計好了一個用於此種狀況的裝飾器:login_requierd()
from django.contrib.auth.decorators import login_required @login_required def my_view(request): '''
若用戶沒有登陸,則會跳轉到django默認的 登陸URL '/accounts/login/ ' (這個值能夠在settings文件中經過LOGIN_URL進行修改)。並傳遞 當前訪問url的絕對路徑 (登錄成功後,會重定向到該路徑)。
使用 create_user 輔助函數建立用戶:
from django.contrib.auth.models import User user = User.objects.create_user(username='',password='',email='')
用戶須要修改密碼的時候 首先要讓他輸入原來的密碼 ,若是給定的字符串經過了密碼檢查,返回 True
使用 set_password() 來修改密碼
user = User.objects.get(username='') user.set_password(password='') user.save
def sign_up(request): state = None if request.method == 'POST': password = request.POST.get('password', '') repeat_password = request.POST.get('repeat_password', '') email=request.POST.get('email', '') username = request.POST.get('username', '') if User.objects.filter(username=username): state = 'user_exist' else: new_user = User.objects.create_user(username=username, password=password,email=email) new_user.save() return redirect('/book/') content = { 'state': state, 'user': None, } return render(request, 'sign_up.html', content) 註冊代碼
@login_required def set_password(request): user = request.user state = None if request.method == 'POST': old_password = request.POST.get('old_password', '') new_password = request.POST.get('new_password', '') repeat_password = request.POST.get('repeat_password', '') if user.check_password(old_password): if not new_password: state = 'empty' elif new_password != repeat_password: state = 'repeat_error' else: user.set_password(new_password) user.save() return redirect("/log_in/") else: state = 'password_error' content = { 'user': user, 'state': state, } return render(request, 'set_password.html', content) 修改密碼的代碼