閱讀目錄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', #你的數據庫端口 } }
在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 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 person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
{% if %}會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。
{% if num > 100 or num < 0 %} <p>無效</p> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <p>湊活吧</p> {% endif %}
使用一個簡單地名字緩存一個複雜的變量,當你須要使用一個「昂貴的」方法(好比訪問數據庫)不少次的時候是很是有用的
例如: 把一個變量複製給total,在下面就直接能夠用total代替 business.employees.count 來用了
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %}
這個標籤用於跨站請求僞造保護
模版之過濾器
參數
{{obj|filter__name:參數}}
default
若是一個變量是false或者爲空,使用給定的默認值。不然,使用變量的值。例如:
{{ value|default:"nothing" }}
返回值的長度。它對字符串和列表都起做用。例如:
{{ value|length }}
filesizeformat
將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
{{ value|filesizeformat }}
若是 value
是 123456789,輸出將會是 117.7 MB
。
若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
若是 value="hello world"
{{ value|slice:"2:-1" }}
若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
參數:要截斷的字符數
例如:
{{ value|truncatechars:9 }}
若是value是「Joel 是 a >,輸出將爲「Joel i ...」。
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>
這個模版,咱們把它叫做 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>
請注意,子模版並無定義 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.
爲了更好的可讀性,你也能夠給你的 {% 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 %}
使用方法:
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除了異步的特色外,還有一個就是:瀏覽器頁面局部刷新;(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)
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
方式一:
$.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']")}, //方法二 })
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 成爲理想的數據交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提高網絡傳輸效率。
合格的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供開發者使用:
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表單提交同樣