Django 之基礎學習

 

 閱讀目錄css

 

 

 

 

Django MTV模型html

 

Django的MTV分別表明:前端

       Model(模型):負責業務對象與數據庫的對象(ORM)python

       Template(模版):負責如何把頁面展現給用戶mysql

       View(視圖):負責業務邏輯,並在適當的時候調用Model和Templatejquery

       此外,Django還有一個urls分發器,它的做用是將一個個URL的頁面請求分發給不一樣的view處理,view再調用相應的Model和Templateweb

 

 

建立一個Django項目ajax

切換到要建立的目錄下 Django-admin startproject mydjango(自定義名字)

 

啓動Django服務正則表達式

python manage.py runserver 127.0.0.1:8000(能夠不寫地址,有默認)

 

在mysite下建立應用appredis

python manage.py startapp myapp

 

 

同步更改數據庫表或字段

'''
    python manage.py syncdb
     
    注意:Django 1.7.1 及以上的版本須要用如下命令
    python manage.py makemigrations
    python manage.py migrate
    
'''

 

這種方法能夠建立表,當你在models.py中新增了類時,運行它就能夠自動在數據庫中建立表了,不用手動建立。

 

清空數據庫

python manage.py flush

 

 此命令會詢問是 yes 仍是 no, 選擇 yes 會把數據所有清空掉,只留下空表。

 

建立超級管理員

'''
    python manage.py createsuperuser
     
    # 按照提示輸入用戶名和對應的密碼就行了郵箱能夠留空,用戶名和密碼必填
     
    # 修改 用戶密碼能夠用:
    python manage.py changepassword username
    
'''

 

 

 

Django項目環境終端

python manage.py shell

 

這個命令和 直接運行 python 進入 shell 的區別是:你能夠在這個 shell 裏面調用當前項目的 models.py 中的 API,對於操做數據的測試很是方便。

 

ython manage.py dbshell

 

Django 會自動進入在settings.py中設置的數據庫,若是是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。

在這個終端能夠執行數據庫的SQL語句。若是您對SQL比較熟悉,可能喜歡這種方式。

 

更多命令

 python manage.py

 

查看全部的命令,忘記子名稱的時候特別有用。

 

 

 

目錄結構

 

 

 - 下載安裝 pip install django - 建立項目 django-admin startproject mysite PyCharm建立項目 --> File->new project -> 左側選Django ->右側選項目存放路徑 - 目錄結構 -mysite -mysite -urls.py 配置對應關係 URL-->函數 -settings.py 配置文件 -wsgi.py socketserver -views.py 本身寫的函數統一放到這裏 __init__.py -templates 存放模板文件的(html文件) -index.html -class_list.html -static -bootstrap -css -bootstrap.min.css -fonts -js -jQuery.3.2.1.min.js -manage.py 管理你Django項目的(有不少命令) python manage.py runserver IP:PORT

 

 

 回到頂部

修改配置文件

 

模版配置:

 

靜態文件配置:

STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ] # 靜態文件存放位置

 

 

數據庫配置

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.mysql',

        'NAME': 'bookmanage',    #你的數據庫名稱

        'USER': 'root',   #你的數據庫用戶名

        'PASSWORD': '123', #你的數據庫密碼

        'HOST': '', #你的數據庫主機,留空默認爲localhost

        'PORT': '3306', #你的數據庫端口

    }

}
View Code

 在app目錄下的init文件裏寫入

import pymysql

pymysql.install_as_mysqldb

  

 

 配置app

 

 

 新手三件套

 

from django.shortcuts import HttpResponse, render, redirect
    1. HttpResponse('ok') #直接返回文字
    2. render 渲染
        1. render(request, "xx.html")
        2. render(request, "xx.html", {"num": 123,'list':[1,2,3]})  #給以給模板裏的變量傳值
    3. redirect('/login/')  跳轉到xx

 

 回到頂部

視圖層之路由配置系統(views)

 

URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要爲該URL調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。

    ''' urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ] 

參數說明:

    一個正則表達式字符串
    一個可調用對象,一般爲一個視圖函數或一個指定視圖函數路徑的字符串
    可選的要傳遞給視圖函數的默認參數(字典形式)
    一個可選的name參數

    '''

 

 

 

1.簡單配置

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
'''
    NOTE:
一旦匹配成功則再也不繼續 若要從URL 中捕獲一個值,只須要在它周圍放置一對圓括號。 不須要添加一個前導的反斜槓,由於每一個URL 都有。例如,應該是^articles 而不是 ^/articles。 每一個正則表達式前面的'r' 是可選的可是建議加上。

一些請求的例子:

    /articles/2005/3/ 不匹配任何URL 模式,由於列表中的第三個模式要求月份應該是兩個數字。
    /articles/2003/ 將匹配列表中的第一個模式不是第二個,由於模式按順序匹配,第一個會首先測試是否匹配。
    /articles/2005/03/ 請求將匹配列表中的第三個模式。Django 將調用函數
                       views.month_archive(request, '2005', '03')。
    '''

 

 

2.有名分組 ?p<>

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern),其中name 是組的名稱,pattern 是要匹配的模式。捕獲的參數永遠是字符串

這個實現與前面的示例徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:

 /articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數 /articles/2003/03/03/ 請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。

 

 

 

3.指定試圖參數的默認值

 

有一個方便的小技巧是指定視圖參數的默認值。 下面是一個URLconf 和視圖的示例:

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):

    ...

 

在上面的例子中,兩個URL模式指向同一個視圖views.page —— 可是第一個模式不會從URL 中捕獲任何值。若是第一個模式匹配,page() 函數將使用num參數的默認值"1"。

若是第二個模式匹配,page() 將使用正則表達式捕獲的num 值。

 

 

4.路由分發

#At any point, your urlpatterns can 「include」 other URLconf modules. This
#essentially 「roots」 a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),
]

 

url(r'^app02/', include("app02.urls",namespace="app02")),

#include()有三個參數,第一個是分發的位置,
   namesoace是命名空間,在不一樣app的urls裏別名重複時可以使用reverse("命名空間:別名")

  

 

5.傳遞額外的選項給視圖函數(瞭解)

 

URLconfs 具備一個鉤子,讓你傳遞一個Python 字典做爲額外的參數傳遞給視圖函數。

django.conf.urls.url() 函數能夠接收一個可選的第三個參數,它是一個字典,表示想要傳遞給視圖函數的額外關鍵字參數。

例如:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

在這個例子中,對於/blog/2005/請求,Django 將調用views.year_archive(request, year='2005', foo='bar')

這個技術在Syndication 框架中使用,來傳遞元數據和選項給視圖。

 

 

6. URL 的反向解析 起別名

urlpatterns = [
    url(r'^articls/2004/$', views.archive,name='laogou'),
]



<form action="{% url 'laogou' %}" method="post">  提交的時候{% url 'laogou' %} 就變成了articls/2004/

 

反向解析在視圖函數中的用法

from django.core.urlresolvers import reverse

def index(request):

    return HttpResponse(reverse("app02:index"))

#app02是命名空間namespace名字,index是別名,
#使用reverser函數根據別名反向解析url

  

 

 回到頂部

 模版層

 

 

 模板語言

 

模板語言for循環: {% for teacher in teacher_list %} 
{% empty %} teacher_list 爲空要作的事兒
{
% endfor %} {{ 變量名 }} if判斷 {% if %}    {% else %} {% endif %}


引用小組件
-{% include 'nav.html' %}
繼承母板
-{% extends 'base.html' %}

替換模版
  -{% block 名字 %}
    {% endblock %}

別名
   - action="{% url '別名' %}"

引入靜態文件
 {% load static %}

<link rel="stylesheet" href="{% static 'css/style.css' %}" type="text/css" media="all">

 

模版語言變量取值  可深度查詢  用句點符

<h4>{{s}}</h4> <h4>列表:{{ l.0 }}</h4> <h4>列表:{{ l.2 }}</h4> <h4>字典:{{ dic.name }}</h4> <h4>日期:{{ date.year }}</h4> <h4>類對象列表:{{ person_list.0.name }}</h4> 注意:句點符也能夠用來引用對象的方法(無參數方法)。 <h4>字典:{{ dic.name.upper }}</h4>

 

 

模版之標籤

 

for標籤

遍歷每個元素:

{% for person in person_list %}
    <p>{{ person.name }}</p>
{% endfor %}

能夠利用{% for obj in list reversed %}反向完成循環。

遍歷一個字典:

{% for key,val in dic.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}

注:循環序號能夠經過{{forloop}}顯示  

forloop.counter         The current iteration of the loop (1-indexed)
forloop.counter0    The current iteration of the loop (0-indexed)
forloop.revcounter  The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0 The number of iterations from the end of the loop (0-indexed)
forloop.first           True if this is the first time through the loop
forloop.last            True if this is the last time through the loop

 

 

for ... empty

for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

 

 

if 標籤

{% if %}會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。

{% if num > 100 or num < 0 %}
    <p>無效</p>
{% elif num > 80 and num < 100 %}
    <p>優秀</p>
{% else %}
    <p>湊活吧</p>
{% endif %}

 

 

with

使用一個簡單地名字緩存一個複雜的變量,當你須要使用一個「昂貴的」方法(好比訪問數據庫)不少次的時候是很是有用的

例如:  把一個變量複製給total,在下面就直接能夠用total代替  business.employees.count 來用了

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

 

 

csrf_token

這個標籤用於跨站請求僞造保護

 

 

 回到頂部

模版之過濾器

 

 

參數

{{obj|filter__name:參數}}

 

 

default

若是一個變量是false或者爲空,使用給定的默認值。不然,使用變量的值。例如:

    {{ value|default:"nothing" }}

 

length

返回值的長度。它對字符串和列表都起做用。例如:

{{ value|length }}

 

filesizeformat

將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)。例如:

{{ value|filesizeformat }}

 

若是 value 是 123456789,輸出將會是 117.7 MB

date

若是 value=datetime.datetime.now()

{{ value|date:"Y-m-d" }}  

 

slice

若是 value="hello world"

{{ value|slice:"2:-1" }}

 

truncatechars

若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。

參數:要截斷的字符數

例如:

{{ value|truncatechars:9 }}

 

若是value「Joel 是 >,輸出將爲「Joel i ...」

safe

 

Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。好比:

value="<a href="">點擊</a>"

{{ value|safe}}

 

在 py文件中使用:

from django.utils.safestring import mark_safe

mark_safe("<a href='%s'>編輯</a>" % path)

  

 

更多詳見文檔...

 

 

模版繼承

 

Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可讓您建立一個基本的「骨架」模版,它包含您站點中的所有元素,而且能夠定義可以被子模版覆蓋的 blocks 。

經過從下面這個例子開始,能夠容易的理解模版繼承:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}My amazing site{%/span> endblock %}</title>
</head>

<body>
    <div id="sidebar">
        {% block sidebar %}
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
        {% endblock %}
    </div>

    <div id="content">
        {% block content %}{% endblock %}
    </div>
</body>
</html>
View Code

這個模版,咱們把它叫做 base.html, 它定義了一個能夠用於兩列排版頁面的簡單HTML骨架。「子模版」的工做是用它們的內容填充空的blocks。

在這個例子中, block 標籤訂義了三個能夠被子模版內容填充的block。 block 告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。

子模版可能看起來是這樣的:

{% extends "base.html" %}
 
{% block title %}My amazing blog{% endblock %}
 
{% block content %}
{% for entry in blog_entries %}
    <h2>{{ entry.title }}</h2>
    <p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}

extends 標籤是這裏的關鍵。它告訴模版引擎,這個模版「繼承」了另外一個模版。當模版系統處理這個模版時,首先,它將定位父模版——在此例中,就是「base.html」。

那時,模版引擎將注意到 base.html 中的三個 block 標籤,並用子模版中的內容來替換這些block。根據 blog_entries 的值,輸出可能看起來是這樣的:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>My amazing blog</title>
</head>
 
<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>
 
    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>
 
        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>
View Code

請注意,子模版並無定義 sidebar block,因此係統使用了父模版中的值。父模版的 {% block %} 標籤中的內容老是被用做備選內容(fallback)。

 

這種方式使代碼獲得最大程度的複用,而且使得添加內容到共享的內容區域更加簡單,例如,部分範圍內的導航。

這裏是使用繼承的一些提示:

  • 若是你在模版中使用 {% extends %} 標籤,它必須是模版中的第一個標籤。其餘的任何狀況下,模版繼承都將沒法工做。

  • 在base模版中設置越多的 {% block %} 標籤越好。請記住,子模版沒必要定義所有父模版中的blocks,因此,你能夠在大多數blocks中填充合理的默認內容,而後,只定義你須要的那一個。多一點鉤子總比少一點好。

  • 若是你發現你本身在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。

  • If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }} will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.

  • 若是你須要從母模板獲得的塊的內容,block.super } }的{ {變量就能夠了。若是您想添加父塊的內容而不是徹底覆蓋它,這是很是有用的。數據插入使用{ { block.super } }不會自動逃跑了
  • 爲了更好的可讀性,你也能夠給你的 {% endblock %} 標籤一個 名字 。例如:

{% block content %}
...
{% endblock content %}  
  • 在大型模版中,這個方法幫你清楚的看到哪個  {% block %} 標籤被關閉了。

最後,請注意您並不能在一個模版中定義多個相同名字的 block 標籤。這個限制的存在是由於block標籤的做用是「雙向」的。這個意思是,block標籤不只提供了一個坑去填,它還在 _父模版_中定義了填坑的內容。若是在一個模版中有兩個名字同樣的 block 標籤,模版的父模版將不知道使用哪一個block的內容。

 

自定義模版標籤方法

規則:

	規則:
		a. 在任意已經註冊的app中,建立一個 templatetags 的目錄
		b. 建立任意 py文件
		c. 建立一個Libiary的對象,且對象的名稱叫 register

 示例:

from django.conf import settings
import re

from django.template import Library
register = Library()

@register.simple_tag
def func(x,y):
    """
    函數返回什麼,頁面就填充什麼
    :param x:
    :param y:
    :return:
    """
    return x+y

@register.inclusion_tag("rbac/rbac.html")
def menu(request):
    """
    把函數返回的值給裝飾器參數裏的模版渲染,渲染後的標籤放到頁面
    :param request:
    :return:模版裏要用到的數據
    """
    current_url = request.path_info
    #在session中取到用於生成菜單的列表
    menu_list = request.session[settings.MENU_SESSION_KEY]

    menu_dict = {}
    for item in menu_list:
        pid = item['pid']
        if not pid:
            item['active'] = False
            menu_dict[item['id']] = item

    for item in menu_list:
        pid = item['pid']
        url = "^%s$" % item['url']
        if re.match(url, current_url):
            if pid:
                menu_dict[pid]['active'] = True
            else:
                item['active'] = True

    menu_result = {}

    for item in menu_dict.values():
        child_dic = {"title": item["title"], "url": item["url"], "active": item["active"]}
        if item["menu_id"] not in menu_result:
            menu_result[item["menu_id"]] = {'menu_title': item["menu_title"], "active": item["active"], "children": []}
            menu_result[item["menu_id"]]["children"].append(child_dic)
        else:
            menu_result[item["menu_id"]]["children"].append(child_dic)
            if item["active"]:
                menu_result[item["menu_id"]]["active"] = True



    # print(menu_result,"\n==============")
    return {"menu_result":menu_result}
定義
{% for foo in menu_result.values %}
    <div class="item">
    <div class="header">{{ foo.menu_title }}</div>
    {% if not foo.active %}
        <div class="body hide">
    {% else %}
        <div class="body">

    {% endif %}

{% for i in foo.children %}
    {% if i.active %}
        <a style="color: red" href={{ i.url }}>{{ i.title }}</a>
    {% else %}
        <a href={{ i.url }}>{{ i.title }}</a>

    {% endif %}

{% endfor %}
</div>
</div>
{% endfor %}
rbac.html

使用方法:

1. 在文檔頂部導入
{% load 文件名 %}
2.引入css樣式
3.{% func 參數1 參數2 %} {% menu 參數 %}

 

自定義過濾器

@register.filter
def filter_multi(v1,v2):
    return  v1 * v2


#在模版中使用
# num=12
{{ num|filter_multi:2 }} #24
 
{{ num|filter_multi:"[22,333,4444]" }}  #只能有一個參數,能夠在函數中反序列化

  

 

 

 

request & response

 

request的方法: request.POST.get() --> 取提交的數據裏面的參數 request.GET.get("key") --> 取URL裏面的參數 "/login/?key=value" request.POST.getlist() --> 提交的是列表的數據類型 request.get_full_path()--> 獲取請求的URL(不含域名)
request.get_path() ---> 獲取請求地址,不含數據部分
request.path_info() -->同上
request.GET.urlencode() -->獲取請求頁面的數據部分(url ?後面的原生字符串) request.method --> 獲取具體的請求方法:GET/POST等 request.COOKIES.get() --> 獲取具體的cookie值
request.COOKIES --> 一個標準的python字典,
request.body -->
一個字符串,表明請求報文的主體。在處理非 HTTP 形式的報文時很是有用,例如:二進制圖片、XML,Json等
request.path --> 一個字符串,和get_full_path同樣,得到請求的路徑組件(不含域名)
request.FILES --> 一個相似於字典的對象,包含全部的上傳文件信息
request.session --> 一個既可讀又可寫的相似於字典的對象
request.is_ajax() --> 判斷是不是ajax發起的請求 是返回True

response響應的方法
response.set_cookie()
response.delete_cookie()

補充:request.MATE

data = request.MATE.get('REMOTE_ADDR') //獲取客戶端的ip地址
           
            CONTENT_LENGTH
            CONTENT_TYPE
            HTTP_ACCEPT_ENCODING
            HTTP_ACCEPT_LANGUAGE
            HTTP_REFERER 引用頁,若是有的話
            HTTP_USER_AGENT 客戶機用戶代理字符串
            QUERY_STRING 查詢字符串,單一的未解析的字符串
            REMOTE_ADDR 客戶機IP地址
            REMOTE_HOST 客戶機hostname
            REQUEST_METHOD 請求方式,好比 GET 或 POST
            SERVER_NAME 服務器 hostname
            SERVER_PORT 服務器端口      

 

 

 

$.ajax   偷偷發送請求不刷新頁面

 

簡介

AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。

同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;
異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。
AJAX除了異步的特色外,還有一個就是:瀏覽器頁面局部刷新;(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)
View Code

 

 

ajax優勢特色:

優勢:

  • AJAX使用Javascript技術向服務器發送異步請求;
  • AJAX無須刷新整個頁面;
  • 由於服務器響應內容再也不是整個頁面,而是頁面中的局部,因此AJAX性能高;

特色:

  • 異步
  • 局部刷新

 

簡單使用:

 $.ajax({ url: "/URL/", type: "POST", data: {"name": "alex"}, success: function(data){ // data就是後端發過來的數據字符串 // 前端作反序列化 var dataObj = JSON.parse(data) // 把收到的字符串反序列化成對象 dataObj["status"] // 就能夠拿到具體的值 dataObj.status } }) 後端序列化: dic = {"status": 0, "msg": "哈哈"} import json str = json.dumps(dic) return HttpResponse(str)

 

 

ajax補充

 

contentType  : 發送信息至服務器時內容編碼類型

contentType:默認值: "application/x-www-form-urlencoded"發送信息至服務器時內容編碼類型。
             用來指明當前請求的數據編碼格式;urlencoded格式: 
 "a=1&b=2";若是想以其餘方式提交數據,
             好比contentType:"application/json",即向服務器發送一個json字符串:
               $.ajax("/ajax_get",{
             
                  data:JSON.stringify({
                       a:22,
                       b:33
                   }),
                   contentType:"application/json",
                   type:"POST",
             
               });                          //{a: 22, b: 33}

             注意:contentType:"application/json"一旦設定,data必須是json字符串,不能是json對象

             views.py:   json.loads(request.body.decode("utf8"))

 

    contentType:     "application/x-www-form-urlencoded", :  'user=alex&pwd=123'
                      "application/json"  :   json字符串:  '{"user":"alex","pwd":"123"}'

 

 processData:

要求爲Boolean類型的參數,默認爲true。默認狀況下,發送的數據將被轉換爲對象(從技術角度來說並不是字符串)以配合默認內容類型"application/x-www-form-urlencoded"。
若是要發送DOM樹信息或者其餘不但願轉換的信息,請設置爲false。

參考博客:http://www.cnblogs.com/yuanchenqi/articles/7638956.html  

 

csrf跨站請求僞造

 

方式一:

$.ajaxSetup({
    data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

  

方式二:

<form>
{% csrf_token %}
</form>

$.ajax({<br>...<br>data:{
"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val(); }<br>})

  

方式三: (發送json數據時會用到)

須要引入:     jquery.cookie.js    CDN:https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js

<script src="{% static 'js/jquery.cookie.js' %}"></script>

$.ajax({
 
headers:{"X-CSRFToken":$.cookie('csrftoken')}, //方法一

headers:{"X-CSRFToken":$("[name='csrfmiddlewaretoken']")},  //方法二
 
})

  

jQuery.serialize()

serialize()函數用於序列化一組表單元素,將表單內容編碼爲用於提交的字符串

serialize()函數經常使用於將表單內容序列化,以便用於AJAX提交。

該函數主要根據用於提交有效表單控件的name和value,將它們拼接爲一個可直接用於表單提交的文本字符串,該字符串已通過標準的URL編碼處理(字符集編碼爲UTF-8)。

該函數不會序列化不須要提交的表單控件,這和常規的表單提交行爲是一致的。例如:不在<form>標籤內的表單控件不會被提交、沒有name屬性的表單控件不會被提交、帶有disabled屬性的表單控件不會被提交、沒有被選中的表單控件不會被提交。

與常規表單提交不同的是:常規表單通常會提交帶有name的按鈕控件,而serialize()函數不會序列化帶有name的按鈕控件。

 

 

語法:

jQuery 1.0 新增該函數。

jQueryObject.serialize( )

  

用法:

data:$("#myForm").serialize(),  //組織好form表單內全部的數據

data:$(":checkbox,:radio,#user,[name='csrfmiddlewaretoken']").serialize(),
//組織一些選中的數據

 

  

 $.post  和  $.get

 

不用再聲明 type類型,

其餘同$.ajax{

}
同樣

 

 

 

JS的序列化與反序列化

 

什麼是JSON

JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。
它基於 ECMAScript (w3c制定的js規範)的一個子集,採用徹底獨立於編程語言的文本格式來存儲和表示數據。
簡潔和清晰的層次結構使得 JSON 成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提高網絡傳輸效率。
View Code

 

 合格的json對象:

["one", "two", "three"]

{ "one": 1, "two": 2, "three": 3 }

{"names": ["張三", "李四"] }

[ { "name": "張三"}, {"name": "李四"} ]

 

不合格的json對象:

{ name: "張三", 'age': 32 }                     // 屬性名必須使用雙引號

[32, 64, 128, 0xFFF] // 不能使用十六進制值

{ "name": "張三", "age": undefined }            // 不能使用undefined

{ "name": "張三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}    // 不能使用函數和日期對象
}

 

JS中使用方法

JSON.parse(data) #把收到的字符串反序列化成對象
JSON.stringify() #把對象序列化成字符串
 

 

應用練習小題

 

# 第一題

list1 = [{"num": 1}, {"num": 3}, {"num": 5}, {"num": 7}]

# 如何把上面的列表轉換成下面的列表?

list2 = [1, 3, 5, 7]

tmp2 = [i["num"] for i in list1] print(tmp2) # 第二題

list3 = [
    {"name": "alex", "habit": "抽菸"},
    {"name": "alex", "habit": "喝酒"},
    {"name": "alex", "habit": "燙頭"},
    {"name": "alex", "habit": "Massage"},
    {"name": "egon", "habit": "喊麥"},
    {"name": "egon", "habit": "街舞"},
]
# 如何把上面的列表轉換成下方的列表?
list4 = [
    {"name": "alex", "habit_list": ["抽菸", "喝酒", "燙頭", "Massage"]},
    {"name": "egon", "habit_list": ["喊麥", "街舞"]},
]


list3_2 = {
    "alex": {"name": "alex", "habit": "抽菸", "habit_list": ["抽菸"]},
    "egon": {"name": "egon", "habit": "喊麥", "habit_list": ["喊麥", "街舞"]},
}

ret = {} for i in list3: name = i["name"]  #alex
    if name not in ret: ret[name] = i  #"alex": {"name": "alex", "habit": "抽菸"}
        ret[name]["habit_list"] = [i["habit"], ]  #"alex": {"name": "alex", "habit": "抽菸", "habit_list": ["抽菸"]},
        ret[name].pop("habit") # {'alex':{"name": "alex", "habit_list": ["抽菸", "喝酒", "燙頭", "Massage"]}}
    else: ret[name]["habit_list"].append(i["habit"]) print(ret) print(list(ret.values())) # [
#     {"name": "alex", "habit_list": ["抽菸", "喝酒", "燙頭", "Massage"]},
#     {"name": "egon", "habit_list": ["喊麥", "街舞"]},
# ]

 

 

回到頂部

cookie

 

定義

 是保存在瀏覽器端的「鍵值對」 服務端能夠在用戶瀏覽器寫Cookie --->響應頭裏面會有 Set-Cookie 登錄以後, 瀏覽器每次發請求的時候會攜帶Cookie

 

 

用法

#往瀏覽器寫cookie  response = redirect('/student_list/') response.set_cookie('login2','1',max_age=180) return response #獲取cookie  request.COOKIES.get('login2') #能夠if判斷有沒有

 

 

參數

 set_cookie的參數: key, value='', max_age=None,   --> 超時時間 多少秒以後cookie失效 expires=None,   --> 超時時間 具體時間cookie失效 path='/',       --> URL 只往這個URL寫cookie ---↑上面的必須會 domain=None,    --> 域名 只有這個域名能用 secure=False,   --> 加密用的 Https httponly=False  --> JS代碼不能讀取cookie,只能瀏覽器發請求時攜帶cookie Cookie超時時間 max_age=None,   --> 超時時間 多少秒以後cookie失效 expires=None,   --> 超時時間  具體時間cookie失效

 

 

加言的cookie

 設置加鹽的Cookie response.set_signed_cookie("login2", "1", max_age=10, salt="PythonFullstackS7") 獲取加密的Cookie: request.get_signed_cookie("login2", salt="PythonFullstackS7", default=None)  要手動設置默認值,防止取值拋KeyError的異常

 

 

寫成裝飾器

 

 

 

回到頂部

session

 

 

Session與Cookie相似,但它們最明顯的區別是,Session會將信息保存服務器端,客戶端須要一個session_id,它一段隨機的字符串,
相似身份證的功能,從服務器端中根據這個憑證來獲取信息。而這個session_id一般是保存在Cookie中的,換句話說,Session的信息傳遞通常要借用到Cookie,
若是Cookie被禁用,它則可能經過爲url加上query string來添加session_id。

 

 

 

 

cookie是保存在用戶瀏覽器上的鍵值對
session是保存在服務器端的鍵值對(依賴cookie)
- Django的session:
- 數據庫【默認】
- 文件
- 緩存
    - 緩存加數據庫
- 加密cookie


使用

 a. 建立保存session的表 python manage.py makemigrations python manage.py migrate
b. 在session中設置數據 request.session['xx1'] = 'x1' request.session['xx2'] = 'x1' request.session['xx3'] = 'x1' request.session['xx4'] = 'x1' c. 讀取 request.session.get('xx1') d. 刪除 del request.session['xx1'] 刪除其中一個鍵值對 request.session.delete() 刪除所有session

 

Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:

  • 數據庫(默認)
  • 緩存
  • 文件
  • 緩存+數據庫
  • 加密cookie

 

redis-session

pip install django-redis-sessions

https://www.2cto.com/database/201803/732179.html

 

一、數據庫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,默認修改以後才保存(默認)
 
 
 
b. 使用
 
    def index(request):
        # 獲取、設置、刪除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的隨機字符串
        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失效策略。

二、緩存Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置
 
 
    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,默認修改以後才保存
 
 
 
b. 使用
 
    同上

三、文件Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    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,默認修改以後才保存
 
b. 使用
 
    同上

四、緩存+數據庫Session

數據庫用於作持久化,緩存用於提升效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上  

五、加密cookie Session

a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
b. 使用
 
    同上

  

 

 

回到頂部

分頁

"""
分頁組件使用示例:

    obj = Pagination(request.GET.get('page',1),len(USER_LIST),request.path_info)
    page_user_list = USER_LIST[obj.start:obj.end]
    page_html = obj.page_html() #html字符串

    return render(request,'index.html',{'users':page_user_list,'page_html':page_html})


"""




class Pagination(object):
    def __init__(self,current_page,all_count,base_url,per_page_num=10,pager_count=11):
        """
        封裝分頁相關數據
        :param current_page: 當前頁
        :param all_count:    數據庫中的數據總條數
        :param per_page_num: 每頁顯示的數據條數
        :param base_url: 分頁中顯示的URL前綴
        :param pager_count:  最多顯示的頁碼個數
        """

        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
        if current_page <1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        self.base_url = base_url

        # 總頁碼
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager


        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)  #先後各幾個頁碼

    @property
    def start(self):  #每頁起始位置對應的數據索引
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):   #每頁結束位置對應的數據索引
        return self.current_page * self.per_page_num

    def page_html(self):
        # 若是總頁碼 < 11個:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 總頁碼  > 11
        else:
            # 當前頁若是<=頁面上最多顯示11/2個頁碼
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 當前頁大於5
            else:
                # 頁碼翻到最後
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []

        first_page = '<li><a href="%s?page=%s">首頁</a></li>' % (self.base_url,1,)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li><a href="#">上一頁</a></li>'
        else:
            prev_page = '<li><a href="%s?page=%s">上一頁</a></li>' % (self.base_url,self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
            else:
                temp = '<li><a href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li><a href="#">下一頁</a></li>'
        else:
            next_page = '<li><a href="%s?page=%s">下一頁</a></li>' % (self.base_url,self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="%s?page=%s">尾頁</a></li>' % (self.base_url,self.all_pager,)
        page_html_list.append(last_page)

        return ''.join(page_html_list)
分頁組件
@check_login
def index(request):
    user = request.session.get('user')
    print(user,'userrrrrrrrrrrrrrr')
    users = []
    for i in range(1,212):
        users.append({'id':i,'name':'alex%s'%(i)})
    current_page = request.GET.get('page',1)

    obj = Pagination(current_page,len(users),'/index/',pager_count=7)
    user_list = users[obj.start:obj.end]
    page_html = obj.page_html()

    if request.method == 'GET':
        return render(request,'index.html',{'user_list':user_list,'page_html':page_html,'user':user})
使用示例

 

 

 

回到頂部

文件傳輸

 

form表單提交方式

 

 

取值

在 request.FILES 中取值 f = request.FILES.get("cFile")   #獲得一個文件對象
 f.name #文件名

 

 

 

Ajax 提交方式

 

 

取值同form表單提交同樣

相關文章
相關標籤/搜索