花了2個星期學習了一下Django的基本使用,感覺就是python真的很牛逼,第三方庫真是太豐富了,人生苦短我用python,這句話我是切切實實體會到了。用Django框架寫服務端的代碼,不知道比.net的效率高出多少倍。之前寫.net的時候,爲了把數據庫映射到業務層花大力氣了,又是用EF實體模型,又是用T4模板,從模型層上開始一個接口一個接口的寫到業務層。如今用Django,都是集成的,根本不用管這些,甚至連SQL都不須要會使用,開發速度不知提升多少倍。javascript
這個是個人Django筆記,我聽的老男孩的課,好像是第四期的,16年末的那個版本,兩個大王老師講的仍是很好的。知道了基本使用,接下來就是找個開源項目練一練,練熟了再看看源碼。css
ps. 這是聽得現場筆記,想着本身忘記了回頭看能想起來就行,因此寫的比較零碎。能想到的適合場景就是恰好你也想聽這個課就能夠拿着參考。若是你是想系統的看Django的教程,建議去alex,武沛齊這些大神的博客看,他們寫的是真棒。html
Http:無狀態前端
請求協議的格式java
請求首行.python
Accept:告訴server我能接收的有哪些類型 q是權重的意思mysql
Accept-encoding:壓縮格式,告訴服務器你回覆的壓縮格式jquery
Accept-Language:能接受的語言web
connection:keep-alive 服務器稍微等一下子(默認3000ms),這個也能夠設置成當即斷的模式面試
Host:我訪問的域名,,主機地址
useragent:我這邊的計算機信息啊,瀏覽器信息啊之類的信息,(發給服務器的)
url發送數據的格式:www.baidu.com?username=hhh&pwd=123 就是不安全 數據的數據通常在1k範圍內
get沒有請求體,post纔有,由於get把數據放到後面去了
默認是get的請求方式 a標籤和超連接也都是get請求
post請求
數據再也不地址欄中
數據大小沒有上限
有請求體
若是存在中文,會使用URL編碼
referer:你這個請求從哪裏過來的
響應協議
這個就是server端告訴瀏覽器的一些事情
狀態碼
500 代碼寫錯了
300 定向相關的內容
server:服務器版本信息
寫一個最最簡單的web框架
就是要求寫一個server端,
wsgiref,python內部得服務器,作http解析的
注意那個return後面有個 b 由於要的是字節
environ:服務器打包好了放過來的第一個參數。是一個大的字典。
start_response:就是用來處理請求頭的。
return 返回的就是瀏覽器真正要響應的響應體。
njix(音),真實生產中用這個服務器
根據路徑來調換顯示什麼內容
這個fool是返回的 讀取一個html的內容 注意要加列表的符號 否則會報splite的錯誤
經過字符串讀的時候可能會有問題,這時候能夠考慮先經過字節讀出來,而後轉成字符串。
Django 就是學這4部分的內容
控制器 --url的分發
model--
魔板渲染
view視圖:一個url處理一個函數
MVC MTV
Quit the server with CTRL-BREAK.
model:操做數據庫 ORM的方式
怎麼經過python操做數據庫
怎麼把數據庫的內容更加靈活的渲染到頁面上
這兩點是重點學的也是難點,另外兩點很簡單
經過命令行,建立一個diango項目
mysite2就是一個全局的,這個全局下面有不少的功能。
在這個項目裏面 建一個子項目blog (就好似大的微信微信項目裏有三個獨立的小的功能(朋友圈、聊天..))
至關於把應用分層了,如今這邊說blog博客的應用,那全部的這個功能都在這個裏面了。
pycharm裏面快速的新建一個Django項目
1.在urls裏面 加一個路由 因爲所在的文件夾不一樣 因此須要導入地址
req服務器打包的信息對
return 必定是個httpresponse對象
運行Django的命令
Django的htm文件都往這個文件夾裏面放 若是沒有這個文件夾就本身建
render 函數的第一個必須傳入 request(得對應起來就行) render的功能就是內部作了一個渲染,而後仍是返回httpresponse
他能自動找到的緣由是在setting裏面作了路徑的自動拼接,因此能找到
Django每次修改自動重啓,不須要再關閉了重啓
放jqueery在static文件夾裏,可是爲了讓這個文件夾的路徑讓Django知道,因此須要到setting裏進行配置。
起別名就是爲了之後方便改動,無外乎就是這個緣由
起了別名就不要用真實的了,用了也沒用,必須用別名
添加Jquerry的方法2 推薦使用
這個方式注意須要在開頭加一個東西。。無論哪一種方式,解析完都是同樣的。
要使用static
標籤,首先須要{% load static %}
。
若是把static那個文件放在blog裏,事實上大點的項目都是這麼玩的。
就該這麼一個 十分方便就是由於有虛擬路徑和實際路徑的幫忙
無命名分組
只有分組的纔會有參數更他對應,不加括號的確定沒有參數和他對應
有名分組
?P<>起有名分組 ==這個是老版本的了,注意DJ2.0以後就不是這麼玩的了==
人家在前端起好什麼名字,你這邊就得叫什麼名字
提交註冊
首先經過url進入regist
而後寫完後,點擊提交,這個前端訪問一個連接,這個連接仍是指向了regist
能夠經過一個視圖作兩件事,只要他們的方式不一樣就行
同源的概念
==這個reg對應上能夠這麼理解:在html裏寫的時候就是在找 這個表單的信息給服務器的哪一個函數去執行呢(這個函數確定往前就是對應的一個連接了),,而後後端path(URL)那邊氣的別名,就是指示那個去執行表單提交過來的信息的函數==
URL如今都在全局的一個項目裏面了,若是項目多了就很差使了。沒有一個很好的解耦。
但願全局作一個分發,發到我的。
推薦使用render問題少。。瞭解下面那個方法,由於其餘人用
把局部變量轉換成鍵值對的locals,
request也是局部變量,因此也能夠傳過去,還能夠用裏面的屬性
跳轉函數:redirect
從一個視圖裏作完了須要去另外一個頁面,就用這個
跳轉和直接render的區別:
模板的組成:HRML代碼+邏輯控制代碼
邏輯控制代碼的組成
pycharm裏面搞到shell的方法
這個render到底隱藏了哪些?
日後面傳不必定是字符串,列表啊 字典啊 類啊 均可以滴 萬能句點符號
內置函數 處理字符串方便一些
計數器
各類計數器
遍歷到某個元素若是是空的時候作出什麼處理
Django第一次post是禁止的,除非帶着身份驗證的token數據。
這個流程就是用瀏覽器訪問的時候會把這個祕鑰發過來,,而後post提交的時候會帶着祕鑰一塊兒去
這個整完了得重啓一下,好像是路徑不能自動的更新
這個傳的變量的個數,就是一個,若是要多個,那就弄個列表
自定義標籤的參數不限制,能夠有多個
建一個新的Django
先搭出一個這樣的框架
先寫一個基礎了html,裏面分塊,這個塊就是能夠修改的。
字版的第一句話就是集繼承過來
include添加
多對多的關係用三張表
一對一,兩張表怎麼弄
其實數據庫只是提供了一對多的關係,多對多的關係個一對一的關係都是從一對多的關係上改過來的。
ORM 對象關係映射表
經過python的類對數據路的表進行操做
makemigrations 和 migrate
D:\Python37\python37.exe manage.py makemigrations (這一步只是建立了一個腳本,並無和數據庫打交道,在blog下的migration文件夾裏建立的腳本)
D:\Python37\python37.exe manage.py migrate
默認是鏈接sqlite數據庫,若是是要鏈接mysql數據庫,須要在設置裏作一些修改
改動一下表的字段
增
方式一:
方拾二:
改
法一 :這種方法是能夠同時改多個的 。這種update的方法效率高,單對單,就改一個。
法二 :這種方法只能改一個 save效率低,由於沒有改動的也會給更新一下
經過設置,打印出ORM執行時所使用的sql語句的日誌
刪除
雙下劃線的特殊功能,模糊查詢
一個2.0版本的新要求,視頻的版本沒有這個
一對多的直接點出來確定是一個對象
涉及到外鍵的一些查詢
方法一: 有點麻煩
方法二
publish找book表關聯的內容
==這個後面接04 03是補充的,有些錯亂==
publish加上引號就是按照映射關係去找,也就是加載完去找,因此能夠publish這個類放在book這個類的哪裏都行。可是若是publish不加上引號,那就是按照變量關係去找的了,那麼publish這個類就得放在book這個類的上面。
上承接02,多表查詢的任務(找符合外鍵條件的一個任務)
推薦自動帶的那個方式 manytomany
多對多前提是有兩張多對多的表
==上述第三個表(本身寫的那個表)的方法不經常使用,這個多是一家之言,主要是以爲麻煩==
聚合函數
分組
能夠理解爲:先分組,而後sum是對每一個組進行操做
生成器的做用就是:節省內存
數據量很少還反覆要用的話,緩存就行。
若是數據量萬級別以上,仍是建議用迭代器
Django牛逼的組件
url
views
models
templates
admin
在、
註冊->建立超級用戶->在頁面裏看
admin關於數據庫的後臺管理
如今想在原來的上面橫着顯示一堆字樣 ,,須要先寫已給類,,而後告訴admin
1.讓框子變的可修改
2.listdisable裏不能加多對多的關係
顯示字段的時候換個別名
按照某個字段排序
cookie和session都有默認放在某個表裏的,因此若是要用這個你就須要把這個表給初始化出來。(用migrate的那些指令)
若是隻有一個cookie的話,全部信息都放在客戶端,不安全,容易被竊取。
cookie就像是客戶端的錢包
session就像是服務端的錢包
session在Django裏會默認存到數據庫裏
若是排除安全和你不嫌棄來回傳輸慢的化,cookies也是能夠本身完成這些功能的,事實上人們一開始也是這麼作的,後來拿session來解決cookies遇到的問題的。 我把鑰匙(cookies)給你你下次帶着鑰匙來,用戶的哪些資料(session對應的東西)我都放在數據庫裏面。拿着鑰匙打開了數據庫的內容。
登陸的時候若是用戶名和密碼對應上了,那就把兩個關鍵字(islogin和user)存到session裏。每次登陸index頁面的時候都去看一下session裏(按照islogin鍵去找)的islogin是否是爲true,若是是true就繼續往下走,若是不是true那就返回登陸界面,讓用戶登陸。
def login(request): print("cookies",request.COOKIES) print("sessions",request.session) if request.method=="POST": name=request.POST.get("user") pwd=request.POST.get("pwd") print("name=======",name) print("pwd==========",pwd) if name=="yuan" and pwd=="123":#這邊在假設若是登陸成功了 #若是登陸成功了,就給這兩個保存起來 #session會自動把這個存到數據庫裏面。 request.session["is_login"]=True request.session["user"]=name return redirect("/index") return render(request,"login.html")#若是沒有登陸成功,就是還返回其login的界面 def index(request): if request.session.get("is_login",None): name=request.session.get("user",None) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!",name) return render(request,"index.html",{"name":name}) else: return redirect("/login")
生命週期指的是用戶在瀏覽器上一點,在你的瀏覽器上都發生了什麼。---
這個是簡單的流程
找到類後,不會首先執行get或post方法,而是執行繼承的view裏的那個dispatch方法,dispatch方法幫助咱們反射找到要執行的get仍是post方法。
渲染完的頁面返回的時候,也是先返回給dispatch而後再返回給用戶。
完整的建一個Django文件
這邊還得加一個token鑰匙,否則post不過去
單表的CRUD
一對多的CRUD
filter和values的跨表都是經過雙下劃線來實現的
多對多
找學生屬於哪一個校區,,跨多個表
反向查找默認是字段_set_這種形式,是能夠改的。
這集沒啥特別的重點,一個是一對多表的CRUD,還有一個就是模板語言裏怎麼將下拉列表的框框變成默認的,就是怎麼checked。
若是定義了related_name,就經過related_name對它進行反向操做
總結一下
感受不到第三張表的存在,這就是manytomany的魅力。
多對多的反向必須加上relatedname,,不加就不能反向查了。
加了value就是數字了,就不能再點了
c
對static裏面的內容分個類
http://fontawesome.dashgame.com/ 專業圖標 注意下面的使用方法
經過寫ID綁定觸發的方式把按鈕和模態關聯起來。
選兩個標籤的時候注意這個寫法啊,一個引號裏面寫逗號
無心中調試出的一個知識點
須要值得注意的是:可能會出現,剛開始加頁面時給全部的控件都綁定了事件,而後再ajax添加新的表單行後忘記給行裏面的控件添加新的事件(57-bug修復)
解決方法,用事件委託來解決,何時點擊,何時綁定。
方式一:
方式1的缺點就是,和格子的對於關係太嚴格了。要是再增長一列就完犢子了。
方法二:
方法二的思想就是經過給每個td上增長一個屬性,而後經過js對各個表格進行精準的操做。這樣的好處就是即便外面的再增長或者刪除或調換一列,這個js代碼都不須要大換。
<div class="container"> <table class="table table-bordered table table-striped" id="tb"> <thead> <th>姓名</th> <th>性別</th> <th>年齡</th> <th>班級</th> <th>操做</th> </thead> <tbody id="tb"> {% for row in stu_list %} <tr nid="{{ row.id }}"> <td na="user">{{ row.username }}</td> <td na="gender">{{ row.gender }}</td> <td na="age">{{ row.age }}</td> <td na="cls_id" cid="{{ row.cs_id }}">{{ row.cs.title }}</td> <td> <a href="del_students.html?nid={{ row.id }}">刪除</a> | <a class="edit-row">編輯</a> </td> </tr> {% endfor %} </tbody> </table> </div>
function bindEditStudent() { $("#tb").on("click",".edit-row",function () { {# 首先把那個增長的模態頁面給打開 #} $("#editstudentmodal").modal("show"); {# 打開後就要在這個上面去顯示選中的那一行的值 #} {# 取出那一行每一個小個子td裏面的值 #} $(this).parent().prevAll().each(function () { {#對那一行裏的每個元素進行輪詢#} var v=$(this).text(); var n=$(this).attr("na"); console.log(v) if (n=="cls_id")#特殊的特殊處理吧,這個須要拿到的是對於班級的id。。 { //爲了這個特殊處理,在html裏給這個增長了cid屬性 var cid=$(this).attr("cid");{#拿到了這個學生對應的班級的id#} $('#editmodel select[name="cls_id"]').val(cid); } else if(n=="gender"){ //性別也特殊,是單選按鈕,經過 if (v==true){ $("#editmodel :radio[value='0']").prop("checked",true); }else { $("#editmodel :radio[value='1']").prop("checked",true); } }else { //n=age //v=12 $("#editmodel input[name='"+n+"']").val(v); } }) }); }
這張圖的cid沒有賦值,看下一張
增長,編輯的時候建議使用普通的刷新頁面的方式,刪除的時候建議使用ajax的方式
若是非要發字典,把字典用json變成字符串日後發
def index(request): userList=[] for i in range(1,1000): temp={"name":"root"+str(i),"age":i} userList.append(temp) current_Page=request.GET.get("p")#當前想要獲取哪一頁 paginator=Paginator(userList,10)#傳入總共的個數,和一頁顯示多少個 try: posts=paginator.page(current_Page) except PageNotAnInteger: posts=paginator.page(1) except EmptyPage:#當向page()提供一個有效值,可是那個頁面上沒有任何對象時拋出 posts=paginator.page(paginator.num_pages) return render(request,"neizhifenye.html",{"posts":posts})
<head> <meta charset="UTF-8"> <title>Title</title> {#把後端傳過來的列表循環的顯示出來#} {% for item in posts.object_list %} <li>{{ item.name }}-{{ item.age }}</li> {% endfor %} {% if posts.has_previous %} <a href="neizhifenye?p={{ posts.previous_page_number }}">上一頁</a> {% endif %} {% if posts.has_next %} <a href="neizhifenye?p={{ posts.next_page_number }}">下一頁</a> {% endif %} </head>
對Django自帶的分頁功能進行擴展後,前端和後端部分關鍵代碼
這個可使用include形式,就是在前端頁面把頁碼選擇的那一行數據放到一個include的文件夾裏,須要用的時候調出來用。。這樣增長前端代碼的複用率。
{% for item in posts.object_list %} <li>{{ item.name }}-{{ item.age }}</li> {% endfor %} {% if posts.has_previous %} <a href="neizhifenye?p={{ posts.previous_page_number }}">上一頁</a> {% endif %} {% for i in posts.paginator.paper_num_range %} //這邊注意先.出paginator 再paper_num.. {% if i == posts.number %} {# 到了當前頁的給大寫一下 #} <a style="font-size: 30px;" href="neizhifenye?p={{ i }}">{{ i }}</a> {% else %} <a href="neizhifenye?p={{ i }}">{{ i }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="neizhifenye?p={{ posts.next_page_number }}">下一頁</a> {% endif %}
#擴展內置分頁的一些功能 class CustomPaginator(Paginator):#繼承於原理的paginator類 def __init__(self,current_page,per_pager_num,*args,**kwargs): self.current_page=int(current_page)#當前頁 self.per_pager_num=int(per_pager_num)#一頁顯示多少條 super(CustomPaginator,self).__init__(*args,**kwargs) def paper_num_range(self):#這個就是擴展的那個功能 #self.num_pages 總共的頁數 這個參數是從父類那裏繼承過來的 #self.current_page 當前頁(就是瀏覽器申請訪問的那個頁面) #self.per_paper_num 最多顯示頁碼的數量 if self.num_pages<self.per_pager_num: #若是總共須要的頁數還比下面顯示出來的頁數少 return range(1,self.num_pages+1) #那就把總共的頁數都顯示出來 #若是總共須要的頁數特別多 part=int(self.per_pager_num/2) #拿到下面一共要顯示多少欄的一半的值 #好比下面要顯示11個 那就取通常5個 if self.current_page<=part: #若是當前要顯示的頁碼 比通常要寫 return range(1,self.per_pager_num+1) #這種狀況就是 你如今要第2頁,下面顯示11個跳轉頁面的按鈕 #那就應該顯示1--11 if (self.current_page+part)>self.num_pages:#這種狀況就是最後那幾個 當前要的頁面 已經很接近最後那幾個了,這時候就顯示倒數後面幾個就行 return range(self.num_pages-self.per_pager_num+1,self.num_pages+1) #若是上面的if都沒有能經過,那就是最最普通的通常狀況了 return range(self.current_page-part,self.current_page+part+1) def index1(request): userList=[]#模擬要顯示的東西 for i in range(1,1000): temp={"name":"root"+str(i),"age":i} userList.append(temp) cuurent_page=request.GET.get("p") paginator=CustomPaginator(cuurent_page,7,userList,10) try: posts=paginator.page(cuurent_page) except PageNotAnInteger: posts=paginator.page(1) #若是取到的不是整數,那就默認顯示第一頁 except EmptyPage:#若是是空頁面 說明過界了 那就顯示最後一頁 posts=paginator.page(paginator.num_pages) return render(request,"neizhifenye.html",{"posts":posts})
這個裏面的名字(user pwd)必須和前端提交過來的同樣(也就是required.post)裏面存儲的同樣才行。這樣Django纔會有辦法自動識別去找了比較。
後端代碼
from django.shortcuts import render ,redirect,HttpResponse from django import forms from django.forms import fields class F1Form(forms.Form): #對form表單裏的數據類型進行限定 #注意這個名字不能瞎寫,須要和前端傳過來的那個同樣 user=fields.CharField(max_length=18, min_length=3, required=True, error_messages={"required":"用戶名不能爲空", "max_length":"太長了", "min_length":"過短了", "invalid":"..",#全部的格式錯誤關鍵字都是invalid } ) pwd=fields.CharField(min_length=6,required=True) age=fields.IntegerField(required=True) email=fields.EmailField(required=True) def form(request): if request.method=="GET": obj=F1Form return render(request,"form.html",{"obj":obj})#這個地方傳過去是由於能夠利用這個本身生成# #HTML if request.method=="POST": obj=F1Form(request.POST)#這個地方特別注意是request.POST而不是request否則會報isvalid的錯誤 #是否所有驗證成功 if obj.is_valid(): #print("驗證成功",obj.cleaned_data) return redirect("http://www.baidu.com") else: print("驗證失敗",obj.errors) return render(request, "form.html", {"obj": obj})
前端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="fm" action="formtest" method="post"> {#前端利用了傳來的form對象自動生成HTML#} <p>姓名{{ obj.user }}{{ obj.errors.user.0 }}</p> <p>密碼{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p> <p>年齡{{ obj.age }}{{ obj.errors.age.0 }}</p> <p>e-mail{{ obj.email }}{{ obj.errors.email.0 }}</p> <input type="submit" value="提交"> </form> </body> </html>
參考博客: http://www.cnblogs.com/wupeiqi/articles/6144178.html Form 1. 驗證 2. 生成HTML(保留上次輸入內容) 3. 初始化默認是 Form重點: - 字段 用於保存正則表達式 ChoiceField ***** MultipleChoiceField CharField IntegerField DecimalField DateField DateTimeField EmailField GenericIPAddressField FileField RegexField - HTML插件 用於生成HTML標籤 - 特殊的單選或多選時,數據源是否能實時更新?????***** from app01 import models class LoveForm(forms.Form): price = fields.IntegerField() user_id = fields.IntegerField( # widget=widgets.Select(choices=[(0,'alex'),(1,'劉皓宸'),(2,'楊建'),]) widget=widgets.Select() ) def __init__(self,*args,**kwargs): super(LoveForm,self).__init__(*args,**kwargs) self.fields['user_id'].widget.choices = models.UserInfo.objects.values_list('id','username') from django.forms.models import ModelChoiceField from django.forms.models import ModelChoiceField class LoveForm(forms.Form): price = fields.IntegerField() user_id2 = ModelChoiceField( queryset=models.UserInfo.objects.all(), to_field_name='id' ) 注意:依賴models中的str方法
cleand_data就是獲取傳過來的數據
更加簡潔的方式往數據庫裏存儲數據
get請求後在userform裏面設置默認值,這樣返回到頁面渲染後,控件就是有默認值的了
經過用這個組件,能夠定製更多的HTML標籤
這個select就是多選的下拉框
兩種設置控件默認值(也就是這個控件在頁面上顯示什麼值)的方法
一種是建立form對象的時候傳,這個時候能夠初始化全部的控件值
一種是建立控件的時候傳,這個時候只能初始化所在的這個控件的值
一句話生成全部控件的方法,不推薦這兒作,由於雖然方便,可是調整樣式的時候就麻煩了。
form表單傳輸文件的時候須要加上這句話,否則文件傳輸不過來的
單選框和多選框給默認的初值
用的不算太多,不知道用在什麼場合
這些本質就是幫咱們作了正則表達式的封裝
每個field裏面都封裝了一個正則表達式 + 一個默認插件。。這個默認插件就是在_str裏,_str就是調用的時候輸出的那個文本。
額外插的一個知識點:後端往前端傳輸一個字符串,怎麼就能讓前端知道這個字符串的意思不是普通的字符串,而是表明的HTML標籤呢。
複習:簡單的擴展就是若是自帶的正則表達式已經不能知足你的需求了,那麼如何擴展或者是說本身定義正則表達式,有多是多個正則表達式來驗證。
複雜的擴展就是對內容進行一些判斷了,若是內容已經有了,那怎麼弄。
1.簡單擴展 利用Form組件自帶的正則擴展: a. 方式一 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( error_messages={'invalid': '...'}, validators=[RegexValidator(r'^[0-9]+$', '請輸入數字'), RegexValidator(r'^159[0-9]+$', '數字必須以159開頭')], ) b. 方式二 from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid': '...'}) 2.基於源碼流程 a. 單字段 from django.core.exceptions import NON_FIELD_ERRORS, ValidationError class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select(choices=[(0,'alex'),(1,'劉皓宸'),(2,'楊建'),]) ) # 自定義方法 clean_字段名 # 必須返回值self.cleaned_data['username'] # 若是出錯:raise ValidationError('用戶名已存在') def clean_username(self): v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 總體錯了 # 本身詳細錯誤信息 raise ValidationError('用戶名已存在') return v def clean_user_id(self): return self.cleaned_data['user_id'] b. 總體錯誤驗證 class AjaxForm(forms.Form): username = fields.CharField() user_id = fields.IntegerField( widget=widgets.Select(choices=[(0,'alex'),(1,'劉皓宸'),(2,'楊建'),]) ) # 自定義方法 clean_字段名 # 必須返回值self.cleaned_data['username'] # 若是出錯:raise ValidationError('用戶名已存在') def clean_username(self): v = self.cleaned_data['username'] if models.UserInfo.objects.filter(username=v).count(): # 總體錯了 # 本身詳細錯誤信息 raise ValidationError('用戶名已存在') return v def clean_user_id(self): return self.cleaned_data['user_id'] def clean(self): value_dict = self.cleaned_data v1 = value_dict.get('username') v2 = value_dict.get('user_id') if v1 == 'root' and v2==1: raise ValidationError('總體錯誤信息') return self.cleaned_data PS: _post_clean
如何把一個表單序列化,而後用ajax的方式傳輸出去
是什麼致使了這個不是python內部的數據類型卻可以轉換成json,是由於他繼承於dic
規則:自定義方法clean_字段名,必須返回值self。cleaned_data[「username」],若是出錯:raise validationerror(「用戶名已經存在」)
這個本身寫clean函數須要有返回值,由於源碼裏是拿到返回值從新賦值給data。。
本身的感受:這兩步的意思就是先檢查格式,再檢查內容。檢查格式的人家已經給寫好了正則表達式,
檢查內容內容的須要本身去寫,本身去寫的過程當中注意去知足別人的格式。
導入validation的命名空間
有時候進行驗證須要用到不少的前面傳過來的數據,這個時候放在單一的那個變量裏顯然顯得十分的不合適,
這個時候就須要咱們在全部的單一的執行完了以後,再有一個能夠執行全局的校驗的函數。
把某種東西可以保存在文件裏的過程,叫作序列化
這種[ob,obj...]的只能經過Django給的那種方式進行序列化
這個裏面的data數據至關於被序列化了兩次,那麼前端也要解兩次。 success回調的那個arg至關於已經幫忙解開一次了,裏面只要再解開一次就行。
經過values獲取的時候怎麼轉換成json的格式
總結來講,返回的是對象的時候採用內置的序列化方法,而後前端也要反序列化兩次
Django序列化 a.對象 ----用內部的 b.字典 c.元祖 序列化:在JavaScript裏用的是:JSON.parse() ,JSON.stringfy() Django裏 json.dumps()和json.load() 這種python內置的序列化只能處理python內置的數據類型。爲了解決 這個問題,用Django給提供的序列化一下,而後再總體序列化一下。意思就是那個不是數據類型的地方序列化的2次,因此前端那邊也反序列化2次。 Django: json.dumps() json.loads() 問題: serilize: model.TB.objects.all() json: list(model.TB.objects.values()) json: list(model.TB.objects.values_list())
內容回顧: 1.ajax參數 url: type: data: 1. value不能是字典 {k1:'v1',k2:[1,2,3,],k3: JSON.stringify({})} 2. $('').serilizer() dataType:"JSON",# text,html,xml 單詞太長了 traditional: success:function(arg){ # arg=>obj }, error:function(){ } 2. 序列化 JavaScript: JSON.parse() JSON.stringify() Django: json.dumps() json.loads() 問題: serilize: model.TB.objects.all() json: list(model.TB.objects.values()) json: list(model.TB.objects.values_list()) 3. Form 做用:用於驗證+(生成HTML+保存上次提交的數據) 使用: 1.建立類 2.建立字段() 3. 驗證用戶輸入: obj = Form(request.POST,request.FILES) if obj.is_valid(): obj.cleaned_data else: obj.errors 4. clean_字段 5. clean() _post_clean() PS: __all__ 4. 分頁組件 a. 內置 b. 擴展 c. 自定義 5. XSS攻擊 跨站腳本攻擊: 防止: - 其餘人輸入的內容 不用safe - 本身輸入的內容 可用safe <script> for(var i=0;i<9999;i++){ alert(i) } </script> <script> 獲取本地cookie,發送到另一個網站 </script> 今日內容: - 文件上傳 - 普通上傳 - 自定義頁面上傳按鈕 - 基於Form作上傳 - Ajax上傳文件????? - Django Model操做補充 參考博客:http://www.cnblogs.com/wupeiqi/articles/6216618.html 1. 建立類 class UserInfo(model.Model): age = CharFiled(是否爲空,類型,長度,列名,索引=True||||錯誤提示,自定義驗證規則) .. .. ### 一對多 ### 一對一 - ### 多對多 - 第三張表:a.自動建立;b.手動建立; c. 手動+自動 ### 自關聯:互粉 ### a. 索引 b. 一對多: on_delete c. 一對一和一對可能是什麼關係? unique=true d. 多對多: - a.自動建立;b.手動建立; c. 手動+自動 - ### 自關聯:互粉 ### PS:related_name 2. 操做類 obj = UserInfo.objects.all().all().all()
上傳的圖標的製做
三種索引
對admin進行一些操做
對外鍵刪除的時候作一些設置 就是你刪除關聯的時候其餘人會怎麼反應
聯合惟一,就是好比給一我的打標籤 一種標籤只能打一次對一我的
這樣寫就能夠經過m對這個操做了。本身定義第三張表,m的add和set就不能用了,filter還能夠用。
這樣容易亂,不是很推薦
ps:推薦寫relatedname
下面可能會出現跨表操做的時候就加上related,加一個或者加兩個都是能夠的。
using指定鏈接哪一個庫
題1:代碼在執行前做用域已經建立,執行的時候按照做用域去找值就對了
返回inner函數沒有拿到外面來,不拿,人家在編譯的過程當中做用域就已經生成了。result是代指inner函數,inner函數有本身的做用域
因此第一個題目的答案是456
第二題:
js裏沒有類,通常用函數來充當類,函數充當類的時候,通常默認把函數名的首字母大寫。
這個建議去武沛齊的博客上看
這樣發過去會有一個問題,Django的後臺不知道這個究竟是get仍是post,沒法解析出這個body裏面的數據
因此就會發現post和get裏面沒有數據,可是body裏面有數據。
基於ireame和form表單實現的僞造ajax
form提供數據 irame提供通道 把數據發過去
irame的兼容性是最好的
不用動態綁定會出現的一個問題就是,重上到下進行刷新的時候可能會出現上面的用到下面的函數,可是尚未刷新到下面的函數的狀況。
在標籤上綁定的時候那個this爲window,動態綁定this不要傳遞,由於內部的那個就是當前標籤
jsonp是一種方式,添加到scrapt塊裏,而後在再刪除掉。從而實現跨域的請求。
jsonp是一個規則,遠程傳過來時函數包裹着數據
jsonp只能用get,即便你用post,內部也會用get