一、必會的13條html
返回對象列表的python
allajax
filter數據庫
excludedjango
order_byjson
reverse數組
distinct瀏覽器
特殊的對象列表緩存
values安全
values_list
返回對象的
get
first
last
返回布爾值
exist
返回數字的
count
二、單表中雙下滑線
__gt
__lt
__in
__range
__countains
__icountains
__startswith
__istartswith
__endswith
__iendswith
__isnull
正向查詢
按照對象查詢,這個時候只要屢清楚外鍵設置在哪一個方向,按照對象一步一步的
往過屢就ok。
反向查詢
反向查詢的時候經過表名(小寫的類名)_set,拿到這個管理對象,對這個對象
能夠進行表的一些操做。
按字段查詢
按字段查詢的時候就沒有必要屢主外鍵在哪方面,只須要看着要查的結果和條件
而後按雙下劃線方法去查找就ok
例子:
# 查找書名是「1」的書的出版社出版的其餘書籍的名字和價格
ret = models.Publisher.objects.filter(book__title='1').first().books.exclude(title='1').values('title','price')
print(ret)
ret = models.Book.objects.filter(publisher=models.Publisher.objects.filter(book__title='1').first()).exclude(
title='1')
print(ret)
# 查找書名是「1」的書的做者們的姓名以及出版的全部書籍名稱和價錢
ret = models.Author.objects.values('book__title', 'book__price').filter(book__title='1').distinct()
for i in ret:
print(i)
# ret = models.Book.objects.get(title='1').author.values('name', 'book__title', 'book__price').distinct()
# print(ret)查出的數據確定是一條一條的,若是是一對多條,會一行一行的列出來嗎,而後 再篩選
正向查詢
Obj.多對多關係 -》 管理對象
add()
remove()
clear()
set() []
create()
反向查詢
Obj.表名(小寫的類名)_set -》 管理對象
聚合是一個終止語句 aggregate
分組的目的是爲了進行聚合操做
分組的結果放到了字段中(values中)
正着來
若是不指定分組對象,那麼按照表名(表名id)分
反着來
這樣是指定values(字段)(也就是分組名稱)來分組
拿到的是對象
from django.db.model import F
兩個字段之間的比較
子段__gt=F("字段")
字段=F(「字段」) * 2
字段=Concat(F("title"), Value("("), Value("初版"), Value(")"))
from django.db.model import Q
兩個條件之間的或關係
Q(篩選條件) | Q(篩選條件)
二者條件之間的與關係
Q(篩選條件) & Q(篩選條件)
條件取反
~Q(篩選條件)
把一些列的操做(步驟)看成一個事務
所有的步驟都成功才成功
經典例子:銀行轉帳
代碼實現:
import os
if name == 'main': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup()
import datetime
from app01 import models
try:
from django.db import transaction # 事務
with transaction.atomic(): # 裏面是執行的全部步驟
new_publisher = models.Publisher.objects.create(name="火星出版社")
models.Book.objects.create(title="橘子物語", publish_date=datetime.date.today(), publisher_id=10) # 指定一個不存在的出版社id
except Exception as e:
print(str(e))
是一個保存在瀏覽器本地的一組組鍵值對
爲何用cookie?http協議是無狀態的,每次請求都是無關聯的,沒有辦法保存狀態
Network中,請求頭中(隨着request傳到服務器)
禁用以後登錄不了,登錄是配合cookie作的
特性
服務器讓瀏覽器進行保存的cookie
瀏覽器有權利是否進行保存
再次訪問服務器的時候會攜帶相應的cookie
Django使用
獲取
request.COOKIES
設置
ret = HttpRequest("XXX")
ret.set_cookie(key, max-age=5)
刪除
ret = HttpResponse("XX")
ret.delete_cookie(key)
用途
登陸
投票
記錄瀏覽習慣
保存着服務器上的鍵值對
爲何要用session?
cookie保存在瀏覽器上,不安全、
cookie的長度受限制 4096字節
Django中操做session
設置session
request.session[key] = value
request.session.setdefault(key, valuue)
獲取session
request.session[key]
request.session.get(key)
刪除session
del request.session[key] 刪除某一個
request.session.delete() 刪除該用戶的全部數據,不刪除cookie
request.session.flush() 刪除該用戶的全部數據,刪除cookie
設置超時時間
request.session.set_expiry(value)
清除全部過時的session
request.session.clear_expired()
from django.conf import global_settings
SEESSION配置
458行
SESSION_COOKIE_NAME 名字
SESSION_COOKIE_AGE 過時時間
SESSION_SAVE_EVERY_REQUEST = False 每次保存一次session
SESSION_EXPIRE_AT_BROWSER_CLOSE = False 關閉瀏覽器就清除cookie
SESSION_ENGINE = '' 設置引擎
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,默認修改以後才保存(默認)
發請求:a標籤,location,form表單,地址欄
鉤子:在某個位置預留了位置,沒有掛鉤子函數的話繼續執行,若是寫了鉤子函數就執行完後繼續執行。
中間件全部的動做都會走,會影響全局,謹慎使用
settings中的MIDDLEWARE
Django中的中間件?是什麼?
是一個python類用來在全局範圍內處理請求和響應的一個鉤子。
自定義中間件
五個方法
參數,執行時間,執行順序
一、process_request(self, request)
執行時間:在路由匹配以前,在視圖函數執行以前,
參數:
request:視圖函數用到中用到的request
執行順序:按照註冊順序執行
返回值:
None:正常流程
HttpResponse對象:當前中間件後面的中間件的process_request方法
process_Response方法和視圖的Http_Response對象不執行,執行當前
中間件的process_response方法以及以前的process_reques方法
二、process_response(self, request, response)
執行時間:在視圖函數執行以後
參數:
request:視圖函數用到中用到的request
response:視圖函數中返回的response對象,若是中間件返回response對象,就不走
視圖函數了
執行順序:按照註冊順序倒序執行
返回值:
不能爲None,不然會報錯
必須是response對象
三、process_view(self, request, view_func, view_args, view_kwargs)
執行時間:在視圖函數以前,在process_reques方法以後,以及路由匹配以後
參數:
request:視圖函數用到中用到的request
view_func:要執行的視圖函數
view_args:視圖函數的位置參數
view_kwargs:視圖函數的關鍵字參數
返回值:
None:正常流程
HttpResponse對象:他以後的中間件process_view方法、視圖都不執行,執行全部中
間件的process_response方法
執行屬性:按照註冊順序執行
四、process_exception(self, request, exception)
執行時間:
觸發條件:有異常才執行
在視圖函數以後,在process_response以前
參數:
request:視圖函數用到中用到的request
exception:錯誤信息對象
返回值:HttpResponse對象:
None:正常執行
HttpResponse對象:
註冊順序以前的全部中間件的process_exception方法不走了
執行全部中間件的的process_response
執行順序:按照註冊順序倒序執行
五、process_template_response(self, request, response)
執行時間:
觸發條件:返回的response對象要有一個render方法
在視圖函數以後,在process_response方法以前
參數「
request:視圖函數用到中用到的request
response:視圖函數中返回的response對象
返回值:
不能爲None,不然會報錯
必須是response對象
執行順序:按照註冊順序倒序執行(不會截斷,可以重寫)
CSRF中間件
CSRF跨站請求僞造
在form表單中加{%csrf_token%}幹了兩件事
隱藏一個input標籤
生成一個cookie
兩個裝飾器
from django.views.decorators.csrf import csrf_exempt, csrf_protect
csrf_exempt:給單個視圖排除校驗
csrf_protect:給單個視圖必須校驗
源碼分析
process_request
從請求的cookie中獲取csrftoken的值 ——》csrf_token ——》
request.META['CSRF_COOKIE']
preocess_view
若是視圖函數加上了csrf_exempt的裝飾器 不作校驗
若是請求方式是'GET', 'HEAD', 'OPTIONS', 'TRACE' 也不作校驗
其餘的請求方式作校驗
request.META.get('CSRF_COOKIE') —— 》 csrf_token
request_csrf_token = ""
從request.POST中獲取csrfmiddlewaretoken對應的值
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
從請求頭中獲取X-csrftoken 的值
request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
request_csrf_token 和 csrf_token 作對比
若是校驗成功 正常走
若是校驗不成功 拒絕
瀏覽器向服務器發送請求的形式
地址欄輸入地址 回車 GET
form表單 點擊 submit
a標籤
ajax
json是一種數據結構,跨平臺
python中的json數據結構轉換
數據類型
字符串、數字、bool、列表、字典、None
序列化
dumps(python數據類型)
dump(python的數據類型, f)
反序列化
loads
load
js中json數據的轉換
數據類型
字符串、數字、布爾、數組、對象、null
序列化
stringify
反序列化
parse
django中json
JsonResponse
JsonResponse({})
JsonResponse([], safe=False)
是一個與服務器進行交互的技術。(js技術)
特色:
異步
不刷新頁面 數據量小
瀏覽器向服務器發送請求
地址欄輸入地址 回車
form表單
a標籤
ajax
ajax
參數
$('#b1').click(function () {
$.ajax({
url: '/calc/', # url地址
type: 'post', # 請求方式
data: { # 發送的數據
i1: $('[name="i1"]').val(),
i2: $('[name="i2"]').val()
hobby:JSON.stringify(['抽菸','喝酒','燙頭']) # 傳個列表 進行序列化
},
success: function (res) { # 回調函數 成功時調用 res 返回的內容 響應的響應體
console.log(res);
$('[name="i3"]').val(res)
}, error: function (res) { # 回調函數 失敗時調用
console.log('這是錯誤的')
console.log(res)
}
})
});ajax發post請求 經過CSRF驗證的方法
頁面中使用{% csrf_token %}
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
data: {
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val(), # **********
name: 'ward',
age: '18',
},
success: function (res) {
console.log(res);
}
})
});設置請求頭
$('#b1').click(function () {
$.ajax({
url: '/csrf_test/',
type: 'post',
headers: {"X-CSRFToken": $('[name="csrfmiddlewaretoken"]').val()},
data: {
name: 'ward',
age: '18',
},
success: function (res) {
console.log(res);
}
})
});全局設置(本身寫的js代碼)
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
# 從cookie中取值 必要有cookie
有cookie的方式
1. 使用{% csrf_token %}
2. 不使用{% csrf_token %}
from django.views.decorators.csrf import ensure_csrf_cookie
將ensure_csrf_cookie加在視圖上 保證返回的響應有cookie
建立超級用戶
python3 manager.py createsuperuser
認證 校驗 用戶的用戶名與密碼
obj = auth.authenticate(request, username=username, password=password)
認證成功:對象
認真失敗:None
保存登陸狀態 記錄到session
login(request, user)
註銷 刪除session
logout(request)
判斷登陸狀態
requset.user.is_authenticated()
建立用戶
from django.cotrib.auth.models import User
密碼是明文的
User.objects.create(username=username,password=password)
密碼是密文的普通用戶
User.objects.create_user(**form_obj.cleaned_data)
建立超級用戶
User.objects.create_superuser(email='',**form_obj.cleaned_data)
密碼相關
校驗密碼
request.user.check_password('root1234')
設置密碼
request.user.set_password('admin1234')
request.user.save()擴展默認的auth_user表
這內置的認證系統這麼好用,可是auth_user表字段都是固定的那幾個,我在項目中無法拿來直接使用啊!
好比,我想要加一個存儲用戶手機號的字段,怎麼辦?
可能會想到新建另一張表而後經過一對一和內置的auth_user表關聯,這樣雖然能知足要求可是有沒有更好的實現方式呢?
答案是固然有了。
咱們能夠經過繼承內置的 AbstractUser 類,來定義一個本身的Model類。
這樣既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統了。
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
用戶信息表
"""
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11, null=True, unique=True)
def __str__(self):
return self.username注意:
按上面的方式擴展了內置的auth_user表以後,必定要在settings.py中告訴Django,我如今使用我新定義的UserInfo表來作用戶認證。寫法以下:
# 引用Django自帶的User表,繼承使用時須要設置
AUTH_USER_MODEL = "app名.UserInfo"再次注意:
一旦咱們指定了新的認證系統所使用的表,咱們就須要從新在數據庫中建立該表,而不能繼續使用原來默認的auth_user表了。
form
完成的事情
有input標籤,讓用戶能夠填數據
校驗form表單提交數據
提示錯誤信息
Django的form
定義
from django import forms
# 定義form
class RegForm(forms.Form):
user = forms.CharField(label='用戶名')
pwd = forms.CharField(label='密碼')使用
視圖中
def register2(request):
form_obj = RegForm()
return render(request, 'register2.html', {'form_obj': form_obj})模板中
<form action="" method="post">
{% csrf_token %}
{{ form_obj.as_p }}
<p>
<input type="submit" value="註冊">
</p>
</form><form action="" method="post">
<p>
{{ form_obj.user.lable }}
{{ form_obj.user }}
</p>
<p>
{{ form_obj.pwd.lable }}
{{ form_obj.pwd }}
</p>
<p>
<input type="submit" value="註冊">
</p>
</form>總結:
form_obj.as_p ——> 自動生成多個p標籤 包含lable input框
form_obj.user/form_obj.pwd ——> 自動生成某個字段的input框
form_obj.user.errors ——> 某個字段的全部錯誤信息
form_obj.user.errors.0 ——> 摸個字段的錯誤信息的第一個
form_obj.use.id_for_lable
參數
label='用戶名', # 標籤的名字 min_length=6, # 校驗的規則 最小長度 initial='alexdsb', # 初始值 error_messages={ # 自定義錯誤提示 'min_length': '你的長度過短了,還不到6', 'required': '不能爲空'
} widget=widgets.PasswordInput() # 插件 指定字段的類型
校驗
每一個字段有默認的校驗方法
min_length=6
max_length=6
required=False
disabled 是否不可修改
自定義校驗規則
validators = [ 校驗器1,校驗器2 ]
from django.core.validators import RegexValidator
RegexValidator(r'^1[3-9]\d{9}$', '手機號不正經')
自定義函數 from django.core.exceptions import ValidationError
def check_name(value): if 'sb' in value: raise ValidationError('不符合社會主義核心價值觀')
validators = [ check_name, ]. # 校驗函數
鉤子函數
局部鉤子
def clean_phone(self):
value = self.cleaned_data.get('phone')
if re.match(r'^1[3-9]\d{9}$',value):
return value
raise ValidationError('手機號不正經')全局鉤子
def clean(self):
pwd = self.cleaned_data.get('pwd')
re_pwd = self.cleaned_data.get('re_pwd')
if pwd == re_pwd:
return self.cleaned_data
self.add_error('re_pwd','兩次密碼不一致')
raise ValidationError('兩次密碼不一致')