Django組件

Django的分頁器(paginator)

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})
view

模板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>
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())
more

自定義分頁

自定義分頁組件算法

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 }}
頁碼渲染
表單渲染時使用切片後的數據,便可實現分頁

Cookie與Session

咱們知道HTTP協議是無狀態協議,也就是說每一個請求都是獨立的!沒法記錄前一次請求的狀態。但HTTP協議中可使用Cookie來完成會話跟蹤!在Web開發中,使用session來完成會話跟蹤,session底層依賴Cookie技術。 bootstrap

cookie

其實Cookie是key-value結構,相似於一個python中的字典。隨着服務器端的響應發送給客戶端瀏覽器。而後客戶端瀏覽器會把Cookie保存起來,當下一次再訪問服務器時把Cookie再發送給服務器。 Cookie是由服務器建立,而後經過響應發送給客戶端的一個鍵值對。客戶端會保存Cookie,並會標註出Cookie的來源(哪一個服務器的Cookie)。當客戶端向服務器發出請求時會把全部這個服務器Cookie包含在請求中發送給服務器,這樣服務器就能夠識別客戶端了!後端

  •  Cookie大小上限爲4KB; 
  •  一個服務器最多在客戶端瀏覽器上保存20個Cookie; 
  •  一個瀏覽器最多保存300個Cookie;  

cookie與HTTP頭

Cookie是經過HTTP請求和響應頭在客戶端和服務器端傳遞的: 瀏覽器

  • Cookie:請求頭,客戶端發送給服務器端; 
  • 格式:Cookie: a=A; b=B; c=C。即多個Cookie用分號離開;  Set-Cookie:響應頭,服務器端發送給客戶端; 
  • 一個Cookie對象一個Set-Cookie: Set-Cookie: a=A Set-Cookie: b=B Set-Cookie: c=C  

cookie的覆蓋

若是服務器端發送重複的Cookie那麼會覆蓋原有的Cookie,例如客戶端的第一個請求服務器端發送的Cookie是:Set-Cookie: a=A;第二請求服務器端發送的是:Set-Cookie: a=AA,那麼客戶端只留下一個Cookie,即:a=AA。 

django中的cookie語法

設置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對象,因爲 session爲用戶瀏覽器獨享,因此用戶在訪問服務器的web資源時 ,能夠把各自的數據放在各自的session中,當用戶再去訪問該服務器中的其它web資源時,其它web資源再從用戶各自的session中 取出數據爲用戶服務。

django中的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失效策略。

補充語法
more

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,默認修改以後才保存(默認)

用戶認證組件auth

auth模塊

from django.contrib import auth

django.contrib.auth中提供了許多方法,這裏主要介紹其中的三個:

authenticate()

提供了用戶認證,即驗證用戶名以及密碼是否正確,通常須要username  password兩個關鍵字參數

若是認證信息有效,會返回一個  User  對象。authenticate()會在User 對象上設置一個屬性標識那種認證後端認證了該用戶,且該信息在後面的登陸過程當中是須要的。當咱們試圖登錄一個從數據庫中直接取出來不通過authenticate()的User對象會報錯的!!

user = authenticate(username='someone',password='somepassword')

login(HttpRequest,user)

該函數接受一個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.
    ...

logout(request) 註銷用戶

from django.contrib.auth import logout
   
def logout_view(request):
  logout(request)
  # Redirect to a success page.

該函數接受一個HttpRequest對象,無返回值。當調用該函數時,當前請求的session信息會所有清除。該用戶即便沒有登陸,使用該函數也不會報錯。

User對象

User 對象屬性:username, password(必填項)password用哈希算法保存到數據庫 

user對象的is_authenticated()

若是是真正的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的絕對路徑 (登錄成功後,會重定向到該路徑)。

2.2建立用戶

使用 create_user 輔助函數建立用戶:

from django.contrib.auth.models import User
user = User.objects.create_user(username='',password='',email='')

2.3 check_password(password)

用戶須要修改密碼的時候 首先要讓他輸入原來的密碼 ,若是給定的字符串經過了密碼檢查,返回 True

2.4  修改密碼

使用 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)  

註冊代碼
register
@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)

修改密碼的代碼
password
相關文章
相關標籤/搜索