2. 今日內容 https://www.cnblogs.com/liwenzhou/p/8343243.html 1. Cookie和Session 1. Cookie 服務端: 1. 生成字符串 2. 隨着響應將字符串回覆給瀏覽器 3. 從瀏覽器發送的請求中拿到字符串 cookie就是保存在瀏覽器上的字符串!!! 每一次請求都會攜帶着cookie 把要保存的信息都保存在用戶的瀏覽器上 好處: 服務端不用存,減輕了服務器壓力 壞處: 信息不安全 Session: 搭配Cookie使用 Session本質上,保存在服務端的鍵值對。 好處: 用戶的信息都保存在服務端,安全 壞處: 數據都保存在服務端,存儲壓力比較大 cookie和Session應用場景: 登陸 刷票限制 保存用戶的瀏覽習慣 Django中使用Session: 獲取、設置、刪除Session中數據 request.session['k1'] request.session.get('k1',None) request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在則不設置 # 刪除當前用戶的全部Session數據 request.session.delete() request.session.set_expiry(value) * 若是value是個整數,session會在些秒數後失效。 * 若是value是個datatime或timedelta,session就會在這個時間後失效。 * 若是value是0,用戶關閉瀏覽器session就會失效。 * 若是value是None,session會依賴全局session失效策略。 CBV加裝飾器注意事項: 要將函數裝飾器轉成方法裝飾器 from django.utils.decorators import method_decorator @method_decorator(check_login) 2. 分頁 第幾頁 數據 索引 1 1-10 0-10 2 11-20 10-20 3 21-30 ----------------------------------------------
day 70 內容回顧 1.內容回顧 https://www.cnblogs.com/liwenzhou/p/8343243.html 1.cookie 本質上就是保存在瀏覽器上得鍵值對 爲了解決HTTP請求是無狀態得 能夠用來作登陸 7天免登陸 瀏覽習慣 (每頁顯示多少條) Django 操做Cookie 1.設置Cookie 是在response對象 1.明文的 rep = 響應對象(基礎必備三件套) rep.set_cookie(key,value,..) 2.加鹽的 rep = 響應對象(基礎必備三件套) rep.set_signed_cookie(key,value,salt='加密鹽) 2.獲取Cookie 是在request對象 1.明文的 request.COOKIES.get('key') / request.COOKIES['key'] 2.加鹽的 request.get_signed_cookie(key, default="默認值", salt='', max_age=None) 2.session 1.定義 保存在服務器端的鍵值對,依賴與Cookie 2.Django的session 操做 1.設置session request.session['k1'] request.session.setdefault('k1',123) # 存在則不設置 2.獲取session request.session.get('k1',None) request.session['k1'] 3.刪除session del request.session['k1'] 註銷以後刪除用戶全部的session數據 request.session.delete() 4.將全部Session失效日期小於當前日期的數據刪除 request.session.clear_expired() 5.設置會話Session和Cookie的超時時間 request.session.set_expiry(value) * 若是value是個整數,session會在些秒數後失效。 * 若是value是個datatime或timedelta,session就會在這個時間後失效。 * 若是value是0,用戶關閉瀏覽器session就會失效。 * 若是value是None,session會依賴全局session失效策略。 3.FBV和CBV CBV要加裝飾器須要用到method_decorator # 導入django 提供得工具 把函數裝飾器變成方法裝飾器 from django.utils.decorators import method_decorator 3.分頁 1.自定義的分頁 重在理解! 編程思想的創建是一個積累的過程。不要着急!!,知道怎麼用 2.Djangon自帶的分頁 注意幾個屬性
Cookie的由來javascript
你們都知道HTTP協議是無狀態的。css
無狀態的意思是每次請求都是獨立的,它的執行狀況和結果與前面的請求和以後的請求都無直接關係,它不會受前面的請求響應狀況直接影響,也不會直接影響後面的請求響應狀況。html
狀態能夠理解爲客戶端和服務器在某次會話中產生的數據,那無狀態的就覺得這些數據不會被保留。會話中產生的數據又是咱們須要保存的,也就是說要「保持狀態」。所以Cookie就是在這樣一個場景下誕生。java
什麼是Cookiepython
Cookie具體指的是一段小信息,它是服務器發送出來存儲在瀏覽器上的一組組鍵值對,下次訪問服務器時瀏覽器會自動攜帶這些鍵值對,以便服務器提取有用信息。mysql
Cookie的原理jquery
cookie的工做原理是:由服務器產生內容,瀏覽器收到請求後保存在本地;當瀏覽器再次訪問時,瀏覽器會自動帶上Cookie,這樣服務器就能經過Cookie的內容來判斷這個是「誰」了。git
查看Cookiegithub
咱們使用Chrome瀏覽器,打開開發者工具。ajax
Django中操做Cookie
獲取Cookie
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
參數:
設置Cookie
rep = HttpResponse(...) rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密鹽',...)
參數:
刪除Cookie
def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 刪除用戶瀏覽器上以前設置的usercookie值 return rep
Cookie版登錄校驗
def check_login(func): @wraps(func) def inner(request, *args, **kwargs): next_url = request.get_full_path() if request.get_signed_cookie("login", salt="SSS", default=None) == "yes": # 已經登陸的用戶... return func(request, *args, **kwargs) else: # 沒有登陸的用戶,跳轉剛到登陸頁面 return redirect("/login/?next={}".format(next_url)) return inner def login(request): if request.method == "POST": username = request.POST.get("username") passwd = request.POST.get("password") if username == "xxx" and passwd == "123": next_url = request.GET.get("next") if next_url and next_url != "/logout/": response = redirect(next_url) else: response = redirect("/class_list/") response.set_signed_cookie("login", "yes", salt="SSS") return response return render(request, "login.html")
Session的由來
Cookie雖然在必定程度上解決了「保持狀態」的需求,可是因爲Cookie自己最大支持4096字節,以及Cookie自己保存在客戶端,可能被攔截或竊取,所以就須要有一種新的東西,它能支持更多的字節,而且他保存在服務器,有較高的安全性。這就是Session。
問題來了,基於HTTP協議的無狀態特徵,服務器根本就不知道訪問者是「誰」。那麼上述的Cookie就起到橋接的做用。
咱們能夠給每一個客戶端的Cookie分配一個惟一的id,這樣用戶在訪問時,經過Cookie,服務器就知道來的人是「誰」。而後咱們再根據不一樣的Cookie的id,在服務器上保存一段時間的私密資料,如「帳號密碼」等等。
總結而言:Cookie彌補了HTTP無狀態的不足,讓服務器知道來的人是「誰」;可是Cookie以文本的形式保存在本地,自身安全性較差;因此咱們就經過Cookie識別不一樣的用戶,對應的在Session裏保存私密的信息以及超過4096字節的文本。
另外,上述所說的Cookie和Session實際上是共通性的東西,不限於語言和框架。
Django中Session相關方法
# 獲取、設置、刪除Session中數據 request.session['k1'] request.session.get('k1',None) request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在則不設置 del request.session['k1'] # 全部 鍵、值、鍵值對 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 會話session的key request.session.session_key # 將全部Session失效日期小於當前日期的數據刪除 request.session.clear_expired() # 檢查會話session的key在數據庫中是否存在 request.session.exists("session_key") # 刪除當前會話的全部Session數據 request.session.delete() # 刪除當前的會話數據並刪除會話的Cookie。 request.session.flush() 這用於確保前面的會話數據不能夠再次被用戶的瀏覽器訪問 例如,django.contrib.auth.logout() 函數中就會調用它。 # 設置會話Session和Cookie的超時時間 request.session.set_expiry(value) * 若是value是個整數,session會在些秒數後失效。 * 若是value是個datatime或timedelta,session就會在這個時間後失效。 * 若是value是0,用戶關閉瀏覽器session就會失效。 * 若是value是None,session會依賴全局session失效策略。
Session流程解析
Session版登錄驗證
from functools import wraps def check_login(func): @wraps(func) def inner(request, *args, **kwargs): next_url = request.get_full_path() if request.session.get("user"): return func(request, *args, **kwargs) else: return redirect("/login/?next={}".format(next_url)) return inner def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") if user == "alex" and pwd == "alex1234": # 設置session request.session["user"] = user # 獲取跳到登錄頁面以前的URL next_url = request.GET.get("next") # 若是有,就跳轉回登錄以前的URL if next_url: return redirect(next_url) # 不然默認跳轉到index頁面 else: return redirect("/index/") return render(request, "login.html") @check_login def logout(request): # 刪除全部當前請求相關的session request.session.delete() return redirect("/login/") @check_login def index(request): current_user = request.session.get("user", None) return render(request, "index.html", {"user": current_user})
Django中的Session配置
Django中默認支持Session,其內部提供了5種類型的Session供開發者使用。
1. 數據庫Session SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默認) 2. 緩存Session SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置 3. 文件Session SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir() 4. 緩存+數據庫 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 5. 加密Cookie Session SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 其餘公用設置項: 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,默認修改以後才保存(默認)
CBV實現的登陸視圖
path('book_list/', views.BookList.as_view(),name='book_list'),
from django.views import View
from django.utils.decorators import method_decorator
class LoginView(View): def get(self, request): """ 處理GET請求 """ return render(request, 'login.html') def post(self, request): """ 處理POST請求 """ user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'alex' and pwd == "alex1234": next_url = request.GET.get("next") # 生成隨機字符串 # 寫瀏覽器cookie -> session_id: 隨機字符串 # 寫到服務端session: # { # "隨機字符串": {'user':'alex'} # } request.session['user'] = user if next_url: return redirect(next_url) else: return redirect('/index/') return render(request, 'login.html')
要在CBV視圖中使用咱們上面的check_login裝飾器,有如下三種方式:
from django.utils.decorators import method_decorator
1. 加在CBV視圖的get或post方法上
from django.utils.decorators import method_decorator class HomeView(View): def dispatch(self, request, *args, **kwargs): return super(HomeView, self).dispatch(request, *args, **kwargs) def get(self, request): return render(request, "home.html") @method_decorator(check_login) def post(self, request): print("Home View POST method...") return redirect("/index/")
2. 加在dispatch方法上
from django.utils.decorators import method_decorator class HomeView(View): @method_decorator(check_login) def dispatch(self, request, *args, **kwargs): return super(HomeView, self).dispatch(request, *args, **kwargs) def get(self, request): return render(request, "home.html") def post(self, request): print("Home View POST method...") return redirect("/index/")
由於CBV中首先執行的就是dispatch方法,因此這麼寫至關於給get和post方法都加上了登陸校驗。
3. 直接加在視圖類上,但method_decorator必須傳 name 關鍵字參數
若是get方法和post方法都須要登陸校驗的話就寫兩個裝飾器。
from django.utils.decorators import method_decorator @method_decorator(check_login, name="get") @method_decorator(check_login, name="post") class HomeView(View): def dispatch(self, request, *args, **kwargs): return super(HomeView, self).dispatch(request, *args, **kwargs) def get(self, request): return render(request, "home.html") def post(self, request): print("Home View POST method...") return redirect("/index/")
補充
CSRF Token相關裝飾器在CBV只能加到dispatch方法上
備註:
from django.views.decorators.csrf import csrf_exempt, csrf_protect class HomeView(View): @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): return super(HomeView, self).dispatch(request, *args, **kwargs) def get(self, request): return render(request, "home.html") def post(self, request): print("Home View POST method...") return redirect("/index/")
1.自定義分頁
data = [] for i in range(1, 302): tmp = {"id": i, "name": "alex-{}".format(i)} data.append(tmp) print(data) def user_list(request): # user_list = data[0:10] # user_list = data[10:20] try: current_page = int(request.GET.get("page")) except Exception as e: current_page = 1 per_page = 10 # 數據總條數 total_count = len(data) # 總頁碼 total_page, more = divmod(total_count, per_page) if more: total_page += 1 # 頁面最多顯示多少個頁碼 max_show = 11 half_show = int((max_show-1)/2) if current_page <= half_show: show_start = 1 show_end = max_show else: if current_page + half_show >= total_page: show_start = total_page - max_show show_end = total_page else: show_start = current_page - half_show show_end = current_page + half_show # 數據庫中獲取數據 data_start = (current_page - 1) * per_page data_end = current_page * per_page user_list = data[data_start:data_end] # 生成頁面上顯示的頁碼 page_html_list = [] # 加首頁 first_li = '<li><a href="/user_list/?page=1">首頁</a></li>' page_html_list.append(first_li) # 加上一頁 if current_page == 1: prev_li = '<li><a href="#">上一頁</a></li>' else: prev_li = '<li><a href="/user_list/?page={}">上一頁</a></li>'.format(current_page - 1) page_html_list.append(prev_li) for i in range(show_start, show_end+1): if i == current_page: li_tag = '<li class="active"><a href="/user_list/?page={0}">{0}</a></li>'.format(i) else: li_tag = '<li><a href="/user_list/?page={0}">{0}</a></li>'.format(i) page_html_list.append(li_tag) # 加下一頁 if current_page == total_page: next_li = '<li><a href="#">下一頁</a></li>' else: next_li = '<li><a href="/user_list/?page={}">下一頁</a></li>'.format(current_page+1) page_html_list.append(next_li) # 加尾頁 page_end_li = '<li><a href="/user_list/?page={}">尾頁</a></li>'.format(total_page) page_html_list.append(page_end_li) page_html = "".join(page_html_list) return render(request, "user_list.html", {"user_list": user_list, "page_html": page_html})
class Pagination(object): def __init__(self, current_page, total_count, base_url, per_page=10, max_show=11): """ :param current_page: 當前頁 :param total_count: 數據庫中數據總數 :param per_page: 每頁顯示多少條數據 :param max_show: 最多顯示多少頁 """ try: current_page = int(current_page) except Exception as e: current_page = 1 self.current_page = current_page self.total_count = total_count self.base_url = base_url self.per_page = per_page self.max_show = max_show # 總頁碼 total_page, more = divmod(total_count, per_page) if more: total_page += 1 half_show = int((max_show - 1) / 2) self.half_show = half_show self.total_page = total_page @property def start(self): return (self.current_page - 1) * self.per_page @property def end(self): return self.current_page * self.per_page def page_html(self): if self.current_page <= self.half_show: show_start = 1 show_end = self.max_show else: if self.current_page + self.half_show >= self.total_page: show_start = self.total_page - self.max_show show_end = self.total_page else: show_start = self.current_page - self.half_show show_end = self.current_page + self.half_show # 生成頁面上顯示的頁碼 page_html_list = [] # 加首頁 first_li = '<li><a href="{}?page=1">首頁</a></li>'.format(self.base_url) page_html_list.append(first_li) # 加上一頁 if self.current_page == 1: prev_li = '<li><a href="#">上一頁</a></li>' else: prev_li = '<li><a href="{0}?page={1}">上一頁</a></li>'.format(self.base_url, self.current_page - 1) page_html_list.append(prev_li) for i in range(show_start, show_end + 1): if i == self.current_page: li_tag = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i) else: li_tag = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.base_url, i) page_html_list.append(li_tag) # 加下一頁 if self.current_page == self.total_page: next_li = '<li><a href="#">下一頁</a></li>' else: next_li = '<li><a href="{0}?page={1}">下一頁</a></li>'.format(self.base_url, self.current_page + 1) page_html_list.append(next_li) # 加尾頁 page_end_li = '<li><a href="{0}?page={1}">尾頁</a></li>'.format(self.base_url, self.total_page) page_html_list.append(page_end_li) return "".join(page_html_list)
def user_list(request): pager = Pagination(request.GET.get("page"), len(data), request.path_info) user_list = data[pager.start:pager.end] page_html = pager.page_html() return render(request, "user_list.html", {"user_list": user_list, "page_html": page_html})
2.Django內置分頁
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger L = [] for i in range(999): L.append(i) def index(request): current_page = request.GET.get('p') paginator = Paginator(L, 10) # per_page: 每頁顯示條目數量 # count: 數據總個數 # num_pages:總頁數 # page_range:總頁數的索引範圍,如: (1,10),(1,200) # page: page對象 try: posts = paginator.page(current_page) # has_next 是否有下一頁 # next_page_number 下一頁頁碼 # has_previous 是否有上一頁 # previous_page_number 上一頁頁碼 # object_list 分頁以後的數據列表 # number 當前頁 # paginator paginator對象 except PageNotAnInteger: posts = paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_pages) return render(request, 'index.html', {'posts': posts})
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <ul> {% for item in posts %} <li>{{ item }}</li> {% endfor %} </ul> <div class="pagination"> <span class="step-links"> {% if posts.has_previous %} <a href="?p={{ posts.previous_page_number }}">Previous</a> {% endif %} <span class="current"> Page {{ posts.number }} of {{ posts.paginator.num_pages }}. </span> {% if posts.has_next %} <a href="?p={{ posts.next_page_number }}">Next</a> {% endif %} </span> </div> </body> </html>
BMS settings.py
""" Django settings for BMS project. Generated by 'django-admin startproject' using Django 2.0.1. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'nk!!3wd)(-d!@0(^3+xr_2+1xucs01mj5m$lw%t0z@^c*@_#an' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'BMS.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'BMS.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'bms69', 'HOST':'127.0.0.1', 'PORT':3306, 'USER':'root', 'PASSWORD':'123', } } # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ] LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
BMS urls.py
"""BMS URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ re_path(r"^login/",views.login,name='login'), re_path(r"^logout/",views.logout,name='logout'), re_path(r'^publisher_list/',views.publisher_list,name='publisher_list'), re_path(r'^delete_publisher/',views.delete_publisher,name='delete_publisher'), re_path(r'^home/',views.home,name="home"), # re_path(r'^book_list/',views.book_list,name="book_list"), re_path(r'^book_list/',views.BookList.as_view(),name="book_list"), # 類視圖 要調用as_view() # 以ip和端口後面什麼都沒有,就能匹配上url re_path(r'^$',views.publisher_list), ]
BMS __init__.py
import pymysql pymysql.install_as_MySQLdb()
app01 models.py
from django.db import models # 出版社類 class Publisher(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) def __str__(self): return self.name # 書類 class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) # 書的價格 price = models.DecimalField(max_digits=8, decimal_places=2) # 999999.99 # 出版日期 publish_date = models.DateTimeField(auto_now=True) # datetime.date() # 書只能關聯一個出版社, 外鍵一般建在多的那一邊 publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE) def __str__(self): return self.title # 做者類 class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) # 多對多, 建在哪邊均可以 books = models.ManyToManyField(to="Book", related_name="authors") # 多對多關聯 detail = models.OneToOneField(to="AuthorDetail", null=True,on_delete=models.CASCADE) # 做者詳情數據的id在這張表是惟一的 def __str__(self): return self.name # 做者詳情 class AuthorDetail(models.Model): age = models.IntegerField() addr = models.TextField() # python manage.py makemigrations # python manage.py migrate # # 在項目的bms __init__ 下設置 # import pymysql # pymysql.install_as_MySQLdb()
app01 views.py
from django.shortcuts import render,redirect,HttpResponse from django.urls import reverse from app01.models import * # 判斷用戶有沒有登陸得裝飾器 , def check_login(func): def inner(request,*args,**kwargs): # 把當前訪問得網址拿到 url = request.get_full_path() # login_user = request.COOKIES.get('login', None) # login_user = request.get_signed_cookie('login',default=None,salt='hehe') login_status = request.session.get('login') login_user = request.session.get('user') if login_status == '1': # 登陸成功 print('驗證經過'.center(120,'*')) return func(request,*args,**kwargs) # 執行被裝飾得函數 else: print('驗證失敗'.center(120, '*')) return redirect('/login/?next={}'.format(url)) return inner # 登陸 # def login(request): # # /login/?next=/book_list/ # # /login/?next=/publisher_list/ # if request.method == 'POST': # next_url = request.GET.get('next') # # username = request.POST.get('user') # password = request.POST.get('pwd') # # if username == 'alex' and password == '123': # # 登陸成功,跳轉到首頁 # # 給用戶生成一個字符串,讓它保存在裏遊覽器上(這個字符串就是Cookie) # rep = redirect(next_url) # # 生成字符串 而且隨着響應返回給瀏覽器 # # # rep.set_cookie("login",'alex') # rep.set_signed_cookie("login",'alex',salt='hehe',max_age = 7) # # 7s 以後失效 加密過得cookie # # print('====',rep) # # <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/home/"> # return rep # # return render(request,'login.html') # session版登陸 def login(request): if request.method == 'POST': next_url = request.GET.get('next') username = request.POST.get('user') password = request.POST.get('pwd') if username == 'alex' and password == '123': # 利用session 保存一個login=alex request.session['user'] = 'alex' request.session['login'] = '1' request.session.set_expiry(86400) # 7s 以後失效 設置瀏覽器失效時間 rep = redirect(next_url) return rep return render(request,'login.html') def logout(request): # 把當前用戶得session 都清掉 request.session.delete() return redirect('/login') # 首頁 def home(request): return render(request,'home.html') # 出版社列表 @check_login def publisher_list(request): # # 判斷用戶有沒有 登陸 # # 實際上就是判斷請求得cookie中有沒有login 1 # print(request.COOKIES) # # {'csrftoken': 'NtrDhwNbXcnTSqmxa7wITT1UqccZYu2Z8ywHdf2rYhyURwdtaOAf702tsLkVfqD7', 'login': '1'} # # # if login_user == 'alex': # 登陸成功 # publisher_list = Publisher.objects.all() # return render(request,'publisher_list.html',{'publisher_list':publisher_list,'user':login_user}) # else: # return redirect(reverse('login')) # 查詢出全部數據 # data = Publisher.objects.all() # # 這裏斌不會查詢數據庫,在對data 操做時,纔會查詢數據庫 data[3:10] # # 總共須要多少頁 # # 每頁顯示10條 # per_page = 10 # data_num = data.count() # 數據得總數 # # page_num,more = divmod(data_num,per_page) # # if more: # # page_num += 1 # current_page = request.GET.get('page',1) # # # try: # # current_page = int(current_page) # # except Exception as e: # # current_page = 1 # # if current_page <= 0: # 若是頁面數是 負數 # # current_page = 1 # # elif current_page > page_num: # 若是頁面 大於 總頁面 # # current_page = page_num # # # 頁面最多顯示11個頁面 , 當前頁數 左 + 5 右 + 5 # max_show = 7 # # half_show = max_show//2 # # # 頁面最左邊顯示多少 # # if current_page - half_show <= 1: # # page_start = 1 # # page_end = max_show # # elif current_page + half_show >= page_num: # 若是右邊 越界了 # # page_start = page_num - max_show + 1 # # page_end = page_num # # else: # # page_start = current_page - half_show # # page_end = current_page + half_show # from utils import mypage # obj = mypage.Pagination(data_num,current_page) # 當前頁是第3頁 (3-1)*10 - 3*10 # date_start = (current_page-1) * per_page # 數據從哪開始切 # data_end = current_page * per_page # 數據切到哪 # publisher_list = Publisher.objects.all() # publisher_list = Publisher.objects.all()[20:30] # publisher_list = data[obj.start:obj.end] # # 生成頁碼 # li = [] # # 加一個首頁 # li.append('<li><a href="/publisher_list/?page=1">首頁</a></li>') # # 加一個上一頁 # if current_page == 1: # li.append('<li class="disabled"><a href="/publisher_list/?page={0}"><span aria-hidden="true">«</span></a></li>'.format( # current_page)) # else: # li.append('<li><a href="/publisher_list/?page={0}"><span aria-hidden="true">«</span></a></li>'.format( # current_page - 1)) # for i in range(page_start,page_end+1): # if i == current_page: # tmp = '<li class="active"><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i) # else: # tmp = '<li><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i) # li.append(tmp) # # 加一個下一頁 # if current_page == page_num: # li.append('<li class="disabled"><a href="/publisher_list/?page={0}"><span aria-hidden="true">»</span></a></li>'.format( # current_page)) # else: # li.append('<li><a href="/publisher_list/?page={0}"><span aria-hidden="true">»</span></a></li>'.format( # current_page + 1)) # li.append('<li><a href="/publisher_list/?page={0}">尾頁</a></li>'.format(page_num)) # page_html = "".join(li) data = Publisher.objects.all() data_num = data.count() # 數據得總數 current_page = request.GET.get('page', 1) from utils import mypage obj = mypage.Pagination(data_num,current_page,request.path) publisher_list = data[obj.start:obj.end] page_html = obj.page_html() return render( request, 'publisher_list.html', {'publisher_list': publisher_list,'page_html':page_html} ) # # 書籍列表頁 # @check_login # def book_list(request): # return render(request,'book_list.html') # FBV(function base views) 就是在視圖裏使用函數處理請求。 # CBV版書籍列表 # CBV(class base views)就是在視圖裏使用類處理請求。 from django.views import View # 導入django 提供得工具 把函數裝飾器變成方法裝飾器 from django.utils.decorators import method_decorator '''三個地方可加裝飾器''' # # # @method_decorator(check_login,name='get') # class BookList(View): # # @method_decorator(check_login) # # def dispatch(self, request, *args, **kwargs): # # super(BookList, self).dispatch(request,*args,**kwargs) # # @method_decorator(check_login) # def get(self,request): # current_page = request.GET.get('page',1) # data = Book.objects.all() # from utils import mypage # obj = mypage.Pagination(data.count(),current_page,request.path) # # book_list = data[obj.start:obj.end] # page_html = obj.page_html() # return render(request,'book_list.html',{'book_list':book_list,'page_html':page_html}) # # 使用django 內置得分頁 from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger class BookList(View): @method_decorator(check_login) def get(self,request): current_page = request.GET.get('page',1) data = Book.objects.all() # 用內置得分頁類 獲得一個分頁對象 page_obj = Paginator(data,10) try: # 嘗試去取 current_page ret = page_obj.page(current_page) except PageNotAnInteger: ret = page_obj.page(1) # 返回第一頁 except EmptyPage: ret = page_obj.page(page_obj.num_pages) # 返回最後一頁 return render(request,'book_list2.html',{'book_list':ret,}) def delete_publisher(request): delete_id = request.POST.get('publisher_id') try: Publisher.objects.filter(id = delete_id).delete() ret = {'status':0} except Exception as e: ret = {'status':1,"msg":'刪除失敗'} import json json_ret = json.dumps(ret) return HttpResponse(json_ret)
app01 tests.py
from django.test import TestCase from functools import wraps # # def my_decorator(func): # def wrapper(*args, **kwargs): # '''''decorator''' # print('Calling decorated function...') # return func(*args, **kwargs) # # return wrapper # # @my_decorator # def example(): # """Docstring""" # print('Called example function') # # # print(example.__name__, example.__doc__) # # wrapper ''decorator # coding=utf-8 # -*- coding=utf-8 -*- # from functools import wraps # # # def my_decorator(func): # @wraps(func) # def wrapper(*args, **kwargs): # '''''decorator''' # print('Calling decorated function...') # return func(*args, **kwargs) # # return wrapper # # # @my_decorator # def example(): # """Docstring""" # print('Called example function') # # # print(example.__name__, example.__doc__) # example Docstring
templates book_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>book_list</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <h1>這是書籍列表頁</h1> <a href="/logout">註銷</a> <div class="container"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>ID</th> <th>書籍名稱</th> </tr> </thead> <tbody> {% for book in book_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> </tr> {% endfor %} </tbody> </table> <nav aria-label="..."> <ul class="pagination"> {{ page_html|safe }} </ul> </nav> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </body> </html>
templates book_list2.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>book_list</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <h1>這是書籍列表頁</h1> <a href="/logout">註銷</a> <div class="container"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>ID</th> <th>書籍名稱</th> </tr> </thead> <tbody> {% for book in book_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ book.id }}</td> <td>{{ book.title }}</td> </tr> {% endfor %} </tbody> </table> <nav aria-label="..."> <ul class="pagination"> {% if book_list.has_previous %} <li><a href="/book_list?page={{ book_list.previous_page_number }}">«</a></li> {% else %} <li class="disabled"><a href="#">«</a></li> {% endif %} <li class="active"><a href="/book_list?page={{ book_list.number }}">{{ book_list.number }}</a></li> {% if book_list.has_next %} <li><a href="/book_list?page={{ book_list.next_page_number}}">»</a></li> {% else %} <li class="disabled"><a href="#">»</a></li> {% endif %} </ul> </nav> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> </body> </html>
templates home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>home</title> </head> <body> <h1>這是home頁面!!!</h1> </body> </html>
templates login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> {# action 爲空 表示往當前url 提交 #} {#<form action="" method="post">#} <form action="{{ request.get_full_path }}" method="post"> {% csrf_token %} <input type="text" name="user"> <input type="password" name="pwd"> <input type="submit" value="登陸"> </form> </body> </html>
templates publisher_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>publisher_list</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/plugins/sweetalert/sweetalert.css"> <style type="text/css"> .sweet-alert h2{padding-top: 20px;} </style> </head> <body> <a href="/logout">註銷</a> <div class="container"> <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>ID</th> <th>出版社名稱</th> <th>操做</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.id }}</td> <td>{{ publisher.name }}</td> <td> {# https://github.com/lipis/bootstrap-sweetalert #} <button class="btn btn-danger delete">刪除</button> </td> </tr> {% endfor %} </tbody> </table> <nav aria-label="..."> <ul class="pagination"> {{ page_html|safe }} </ul> </nav> </div> <script src="/static/jquery-3.2.1.min.js"></script> <script src="/static/init_ajax.js"></script> <script src="/static/bootstrap-3.3.7/js/bootstrap.min.js"></script> <script src="/static/plugins/sweetalert/sweetalert.min.js"></script> <script type="text/javascript"> //給刪除按鈕綁定事件 $('.delete').click(function () { var id = $(this).parent().prev().prev().text(); var $currentTr = $(this).parent().parent(); swal({ title: "肯定要刪除嗎? ", text: "刪了就找不回來了", type: "warning", showCancelButton: true, // 顯不顯示取消按鈕 confirmButtonClass: "btn-danger", confirmButtonText: "是,就是刪除", //取消按鈕上的文字 closeOnConfirm: false }, function(){ $.ajax({ url:'/delete_publisher/', type:'post', data:{'publisher_id':id}, success:function (arg) { var ret = JSON.parse(arg); if(ret.status === 0){ $currentTr.remove(); swal("刪除成功!", "你能夠跑路了", "success"); }else{ swal(ret.msg, "你能夠嘗試在刪一次", "error"); } } }); }); }); </script> </body> </html> {# 下載 dist css js 引入 #} {# https://github.com/lipis/bootstrap-sweetalert #} {# https://lipis.github.io/bootstrap-sweetalert/ #}
utils mypage.py
''' 自定義分頁組件 ''' class Pagination(object): def __init__(self, data_num, current_page,url_prefix, per_page = 10, max_show = 11): """ 進行初始化 :param data_num: 數據總數 :param current_page: 當前頁 :param url_prefix: 生成得頁碼得連接前綴 :param per_page: 每頁顯示多少條數據 :param max_show: 頁面最多顯示多少個頁碼 """ self.data_num = data_num self.per_page = per_page self.max_show = max_show self.url_prefix = url_prefix # 把頁碼數算出來 self.page_num, more = divmod(self.data_num, self.per_page) if more: self.page_num += 1 try: current_page = int(current_page) except Exception as e: current_page = 1 if current_page <= 0: # 若是頁面數是 負數 current_page = 1 elif current_page > self.page_num: # 若是頁面 大於 總頁面 current_page = self.page_num self.current_page = current_page # 頁碼數得一半 self.half_show = self.max_show // 2 if self.current_page - self.half_show <= 1: self.page_start = 1 self.page_end = self.max_show elif self.current_page + self.half_show >= self.page_num: # 若是右邊 越界了 self.page_start = self.page_num - self.max_show + 1 self.page_end = self.page_num else: self.page_start = self.current_page - self.half_show self.page_end = self.current_page + self.half_show @property def start(self): return (self.current_page-1) * self.per_page # 數據從哪開始切 @property def end(self): return self.current_page * self.per_page # 數據切到哪 def page_html(self): # 生成頁碼 li = [] # 加一個首頁 li.append('<li><a href="{}?page=1">首頁</a></li>'.format(self.url_prefix)) # 加一個上一頁 if self.current_page == 1: li.append( '<li class="disabled"><a href="#"><span aria-hidden="true">«</span></a></li>') else: li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">«</span></a></li>'.format( self.url_prefix,self.current_page - 1)) for i in range(self.page_start, self.page_end + 1): if i == self.current_page: tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i) else: tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix,i) li.append(tmp) # 加一個下一頁 if self.current_page == self.page_num: li.append( '<li class="disabled"><a href="#"><span aria-hidden="true">»</span></a></li>') else: li.append('<li><a href="{0}?page={1}"><span aria-hidden="true">»</span></a></li>'.format(self.url_prefix, self.current_page + 1)) li.append('<li><a href="{0}?page={1}">尾頁</a></li>'.format(self.url_prefix,self.page_num)) return "".join(li)
myscript.py
# -*- coding:utf-8 -*- import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() # 建立300個出版社 from app01 import models # Publisher.objects.create(name='水星第{}出版社'.format(i)) # obj = Publisher(name='火星出版社') # obj.save() # ret = [] # for i in range(300): # obj = Publisher(name='水星第{}出版社'.format(i)) # ret.append(obj) # ret = [models.Publisher(name='水星第{}出版社'.format(i)) for i in range(300)] # 批量建立300個出版社對象 # models.Publisher.objects.bulk_create(ret) # 只提交一次 # 建立300本書 import random ret = [models.Book(title='番茄物語{}'.format(i),price=random.randint(10, 90),publisher_id=1) for i in range(300)] models.Book.objects.bulk_create(ret)
https://github.com/alice-bj/BMS
view
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})
index.html
<!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>
def index(request): book_list=Book.objects.all() paginator = Paginator(book_list, 15) page = request.GET.get('page',1) currentPage=int(page) # 若是頁數十分多時,換另一種顯示方式 if paginator.num_pages>11: if currentPage-5<1: pageRange=range(1,11) elif currentPage+5>paginator.num_pages: pageRange=range(currentPage-5,paginator.num_pages+1) else: pageRange=range(currentPage-5,currentPage+5) else: pageRange=paginator.page_range 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",locals())
示例:
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</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> <ul> {% for book in current_page %} <li>{{ book.title }} - {{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="?page=1">首頁</a></li> {% if current_page.has_previous %} <li> <a href="?page={{ current_page.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">上一頁</span> </a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Previous"> <span aria-hidden="true">上一頁</span> </a> </li> {% endif %} {% for item in page_range %} {% if current_page_num == item %} <li class="active"><a href="?page={{ item }}">{{ item }}</a></li> {% else %} <li><a href="?page={{ item }}">{{ item }}</a></li> {% endif %} {% endfor %} {% if current_page.has_next %} <li> <a href="?page={{ current_page.next_page_number }}" aria-label="Next"> <span aria-hidden="true">下一頁</span> </a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Next"> <span aria-hidden="true">下一頁</span> </a> </li> {% endif %} <li><a href="?page={{ paginator.num_pages }}">尾頁</a></li> </ul> </nav> </body> </html>
views.py
from django.shortcuts import render,HttpResponse # Create your views here. from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger from app01.models import Book def index(request): ''' 批量導入 book_list = [] for i in range(100): book = Book(title='book_%s'%i,price=i*i) # 單條插入 book_list.append(book) Book.objects.bulk_create(book_list) ''' book_list = Book.objects.all() paginator = Paginator(book_list,6) # 20顯示20個數據 print(paginator.count) # 數據總數 100 print(paginator.num_pages) # 總頁數 13 print(paginator.page_range) # 頁碼的列表 range(1,14) current_page_num = int(request.GET.get('page', 1)) show_page = 7 half_show_page = int(show_page/2) if paginator.num_pages > show_page: # 11 表示顯示11個頁碼 if current_page_num - half_show_page < 1: page_range = range(1,show_page+1) elif current_page_num + half_show_page > paginator.num_pages: page_range = range(paginator.num_pages-show_page+1,paginator.num_pages+1) else: page_range = range(current_page_num-half_show_page,current_page_num+half_show_page+1) else: page_range = paginator.page_range try: # 顯示某一頁具體數據 current_page = paginator.page(current_page_num) print(current_page.object_list) for i in current_page: print(i) except EmptyPage as e: current_page = paginator.page(paginator.num_pages) except PageNotAnInteger as e: current_page = paginator.page(1) return render(request,'index.html',locals()) ''' http://www.cnblogs.com/yuanchenqi/articles/9036515.html 批量插入 Booklist=[] for i in range(100): Booklist.append(Book(title="book"+str(i),price=30+i*i)) Book.objects.bulk_create(Booklist) 分頁器: 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 '''
models.py
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2)
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
線上 Cookie session
http://www.cnblogs.com/yuanchenqi/articles/9036467.html
Cookie : 一個瀏覽器 針對 一個服務器 存儲得 key value 值!
在瀏覽器端得磁盤上存儲
默認時間是2周,可設置失效時間! 就算關機開機,cookie任然存在!!
設置Cookie 用響應體 利用cookie 維持會話得記錄保存狀態!
response = HttpResponse('登陸成功')
HttpResponse() render() redirect() 三個response 均可設置cookie
# 1. 設置失效時間
response.set_cookie('is_login', True, max_age = 15) # 時間 15s 後
import datetime # 固定在哪一個時刻 過時
date = datetime.datetime(year=2018,month=5,day=29,hour=14,minute=32,seconds=10)
response.set_cookie('username',username,expires=date)
# 2. 有效路徑
response.set_cookie('username',username,path='/index/')
# 3. 清cookie 瀏覽器
ctrl + shift + delete
# 4. 設置上次訪問時間
import datetime
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
設置爲北京時間
TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai'
last_time = request.COOKIE.get('last_visit_time','')
response.set_cookie('last_visit_time',now)
return render(request,'index.html',{'username':username,'last_time':last_time})
# 5.利用cookie設置 上次訪問得商品
。。。
return response
is_login = request.COOKIE.get('is_login')
if is_login:
username = request.COOKIE.get('username')
return render(request,'index.html',{'username':username})
else:
return redirect('/login/')
-------------------------------------
session:
寫:
request.session['is_login'] = True
request.session['username'] = "yuan"
import datetime
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
request.session['last_visit_time'] = now
if request.COOKIE.get('sessionid'):
在django-session表中更新一條記錄:
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'alice'}
else:
1. 生成隨機字符串
2. response.set_cookie('sessionid',2312312sadasdasdas2312)
3. 在django-session表中建立一條記錄:
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'yuan'}
讀:
request.session.get('is_login')
username = request.session.get('username')
last_visit_time = request.session.get('last_visit_time')
1. request.COOKIE.get('sessionid') # 2312312sadasdasdas2312
2. django-session表中得記錄過濾
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'yuan'}
obj = djsngo-session.object.filter(session-key="2312312sadasdasdas2312").first()
3. obj.session-data.get('is_login')
註銷:
del request.session['is_login'] # 不建議這麼作; 要刪就要刪整條記錄
request.session.flush()
1. session_str = request.COOKIE.get('sessionid')
2. django-session.object.filter(session-key=session-str).delete()
3. response.delete_cookie('sessionid')
session 配置:
Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。
配置 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,默認修改以後才保存(默認)
總結:
1. 寫cookie:
response.set_cookie(key,value)
2, 讀cookie:
request.COOKIE.get(key)
3. 寫session
request.session[key] = value
注意django對應得操做
if request.COOKIE.get('sessionid'):
在django-session表中更新一條記錄:
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'alice'}
else:
1. 生成隨機字符串
2. response.set_cookie('sessionid',2312312sadasdasdas2312)
3. 在django-session表中建立一條記錄:
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'yuan'}
4. 讀session:
request.session[key]
1. request.COOKIE.get('sessionid') # 2312312sadasdasdas2312
2. django-session表中得記錄過濾
session-key session-data
2312312sadasdasdas2312 {"is_login":True,"username":'yuan'}
obj = djsngo-session.object.filter(session-key="2312312sadasdasdas2312").first()
3. obj.session-data.get('is_login')
5. 刪session:
request.session.flush()
1. session_str = request.COOKIE.get('sessionid')
2. django-session.object.filter(session-key=session-str).delete()
3. response.delete_cookie('sessionid')