Django基礎(URL,Template,Models)
1. Django初步使用
1.1 MVC和MTV框架
1.1.1 MVC
- M:模型,負責業務物件和資料庫的對映(ORM)
- V:檢視,負責與使用者的互動(頁面)
- C:控制器,負責與使用者的互動(頁面)
1.1.2 MTV
- M:模型(Model),負責業務物件和資料庫的關係對映(ORM)
- T:模板(Template),負責如何把頁面展示給使用者(html)
- V:檢視(View),負責業務邏輯,並在適當時候呼叫Model和Template
此外還需一個URL分發器,將一個個URL請求分發給不同的View處理。
1.2. Django的安裝和使用
直接通過pip3 install去下載對應版本的Django即可。
1.2.1 建立django project
先新建一個Django_projects資料夾,進入這個資料夾後,建立第一個專案。
django-admin startproject mysite # 建立了一個名為"mysite"的Django 專案
django project的目錄結構:
mysite |--- manage.py # Django專案裡的工具,可以通過它呼叫django shell和資料庫,啟動關閉專案與專案互動等 |--- mysite
|--- __init__.py |--- settings.py #包含了專案的預設設定 |--- urls.py # 負責把URL模式對映到應用程式 |--- wsgi.py
注意:
- 建立Django專案不能用中文
- 要將django-admin.exe的路徑配置到環境變數中
- 這個檔案的位置一般在python直譯器目錄的Scripts目錄下
啟動Django:
python manage.py runserver 127.0.0.1:8080 # 此時已經可以啟動django專案了,只不過什麼邏輯也沒有
1.2.2 建立應用
通過manage.py可以建立應用
python manage.py startapp app01# 通過執行manage.py檔案來建立應用,
# 應該在這個manage.py的檔案所在目錄下執行這句話,因為其他目錄裡面沒有這個檔案
python manage.py startapp app02 # 每個應用都有自己的目錄,每個應用的目錄下都有自己的views.py檢視函式和models.py資料庫操作相關的檔案
1.2.3 修改settings配置
將URL中的路徑和本地檔案系統上的路徑做對應關係對映:
STATIC_URL = '/static/' # 這裡表示的是URL中的路徑 STATICFILES_DIRS=( os.path.join(BASE_DIR,"statics"), # 這裡表示的是本地檔案系統的路徑 )
將csrf中介軟體選項暫時註釋:
# 'django.middleware.csrf.CsrfViewMiddleware', #這裡先註釋掉
1.2.4 啟動專案
python manage.py runserver 127.0.0.1:8080 # 本機可以不寫ip地址了 預設是本機的8000埠
2. URL路由系統
2.1 基本使用格式
django2.0之後是使用了path,但是也向下相容使用url,匯入url即可。
from django.conf.urls import url urlpatterns = [ url(正則表示式, views檢視函式,引數,別名), ] # 正則表示式:一個正則表示式字串 # views檢視函式:一個可呼叫物件,通常為一個檢視函式或一個指定檢視函式路徑的字串 # 引數:可選的要傳遞給檢視函式的預設引數(字典形式) # 別名:一個可選的name引數
2.2 URL分組
2.2.1 無名分組
所謂無名分組,其實就是給檢視函式傳遞位置引數。
將要傳遞的引數在放入小括號()中,然後在對應的檢視函式中按順序接收對應的引數即可。
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [# 無名分組 (給應用檢視函式傳遞位置引數) url(r'books/(\d{4})/$', views.year), # 完全匹配 url(r'^books/(\d{4})/(\d{2})/$', views.year_mouth), url(r'^books/(\d{4})/(\d{2})/(\d{2})/$', views.year_mouth_day), ]
- urlpatterns中的元素按照書寫順序從上往下逐一匹配正則表示式,一旦匹配成功則不再繼續
- 若要從URL中捕獲一個值,只需要在它周圍放置一對圓括號(分組匹配)
- 不需要新增一個前導的反斜槓(也就是寫在正則最前面的那個/),因為每個URL 都有
- 例如,應該是^books而不是 ^/books
- 每個正則表示式前面的 'r' 是可選的但是建議加上
- ^books& 以什麼結尾,以什麼開頭,嚴格限制路徑
-
# 是否開啟URL訪問地址後面沒有/跳轉至帶有/的路徑的配置項,預設是開啟的 APPEND_SLASH=True
2.2.2 有名分組
所謂有名分組,就是捕獲URL中的值並以關鍵字引數形式傳遞給檢視函式。
分組命名正則表示式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式。
urlpatterns = [ url(r'^articles/(?P<year>[0-9]{4})/$', views.year),
# 某年的,(?P<year>[0-9]{4})這是命名引數,那麼函式year(request,year),形參名稱必須是year這個名字
# 如果這個正則後面沒有寫$符號,即便是輸入了月份路徑,也會被它攔截下拉,因為它的正則也能匹配上 url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.details), ]
- 也可以對應views函式的預設值引數,也就是說檢視函式中可以指定引數的預設值
- 捕獲的引數永遠都是字串
2.3 URL分發
因為一個專案中可能有多個應用,所以我們需要對URL做分發。
要將新建立的應用新增到setttings配置檔案中的INSTALLED_APPS中
使用include即可完成對URL的分發:(include需要手動匯入)
from django.conf.urls import url,include urlpatterns = [ # 輸入不同的url找到不同的app 分發給不同的應用的urls.py url(r'^app01/', include('app01.urls')), # 這時app01中的urls只需要處理app01後面的那部分url了 url(r'^app02/', include('app02.urls')), ]
2.4 URL別名
通過給URL定義一個別名來防止URL路徑更改後URL失效。
使用別名:
# 給url匹配模式起名為 home,別名不需要改,路徑就可以隨便改了,別的地方要使用這個路徑,則用這個別名即可 url(r'^home', views.home, name='home'), url(r'^index/(\d*)', views.index, name='index'),
在模板中的引用:
{% url 'home' %} #模板渲染的時候,被django解析成了這個名字對應的那個url,這個過程叫做反向解析
3. Views檢視函式
http請求中產生的核心物件:(所在位置:django.http)
- http請求:HttpRequest物件
- http響應:HttpResponse物件
3.1 HttpRequest物件
1) path
- 請求頁面的全路徑,不包括域名,也不包括引數
2) method
- 請求中使用的HTTP方法的字串表示,全大寫表示
if request.method=="GET": do_something() elif request.method=="POST": do_something_else()
3) GET
- 包含所有HTTP GET引數的類字典物件
4) POST
- 包含所有HTTP POST引數的類字典物件
- 伺服器收到空的POST請求的情況有可能發生,也就是說,表單form通過HTTP POST方法提交請求,但是表單中可能沒有資料
- 因此不能使用if req.POST來判斷是否使用了HTTP POST 方法;應該使用 if req.method=="POST"
5) session
- 唯一可讀寫的屬性,代表當前會話的字典物件
- 自己有啟用Django中的session支援時該屬性才可用
6) COOKIES
- 包含所有cookies的標準Python字典物件
- keys和values都是字串
7) FILES
- 包含所有上傳檔案的類字典物件
- FILES中的每一個Key都是<input type="file" name="" />標籤中 name屬性的值,FILES中的每一個value同時也是一個標準的python字典物件,包含下面三個Keys:
- filename: 上傳檔名,用字串表示
- content_type: 上傳檔案的Content Type
- content: 上傳檔案的原始內容
8) user
- 是一個django.contrib.auth.models.User物件,代表當前登陸的使用者
- 如果訪問使用者當前沒有登陸,user將被初始化為django.contrib.auth.models.AnonymousUser的例項
- 可以通過user的is_authenticated()方法來辨別使用者是否登陸:if req.user.is_authenticated()
- 只有啟用Django中的AuthenticationMiddleware時該屬性才可用
方法:
- get_full_path()
- 得到包含引數的path
- request.POST.getlist("")
3.2 HttpResponse物件
HttpResponse物件由我們自己建立,且每個view請求處理方法必須返回一個HttpResponse物件。
HttpResponse類在django.http.HttpResponse,需要手動匯入。
HttpResponse物件上擴充套件的常用方法:
- 頁面渲染:
- render()
- render_to_response()
- 頁面跳轉:
- redirect("路徑")
- 直接返回:
- HttpResponse("xxoo")
- locals()函式可以直接將函式中所有的變數傳給模板
-
return render(req,"my backend.html",locals())
-
render和redirect的區別:
- render的頁面需要模板語言渲染,且url並沒有變化,還是保持不變
- redirect是直接跳轉,url會改變
4. Template模板系統
模板渲染的兩種特殊符號:
- 變數相關的用 {{ }}
- 邏輯相關的用 {% %}
4.1 變數的使用
4.1.1 語法格式
使用雙大括號來引用變數:
{{ var_name }}
Views函式中的程式碼:
def current_time(req): now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':now}) # 在模板中,就可以使用{{current_date}}來引用這裡的變數
4.1.2 深度變數的查詢
利用點號來查詢深度變數
點號可以訪問列表索引,也可以通過字典的鍵來訪問對應的值,同樣也可以訪問物件的屬性以及方法
{{ items.2 }} # 通過列表的索引來獲取對應的值 {{ person.name }} # 通過字典的key來獲取對應的值 {{ date.month }} # 通過點號來訪問物件的屬性 {{ var.upper }} # 通過訪問對應的方法來呼叫它
4.1.3 變數的過濾器(filter)
1)語法格式
- {{ obj|filter:param }}
2)常用的過濾器
# default:如果值是False,就替換成設定的預設值,否則就是用本來的值 {{ value|default:'值是False'}}
# length:返回值的長度,作用於字串和列表 {{ name_list|length }}
# slice:切片,支援python中可用的所有資料型別 {{ name_list|slice:'1:3' }} {{ s|slice:'1::2' }} # add:給變數加上相應的值 {{ value|add:3 }} # capfirst:首字母大寫 {{ value|capfirst }} # upper:字元轉換成大寫 {{ value|upper }} # cut:從字串中移除指定的字元 {{ value|cut:' '}} # date:格式化日期字串 {{ value|date:'Y-m-d' }} # join:設定連線符將可迭代物件的元素連線在一起,與字串的join方法相同 {{ name_list|join:'_'}} {{ tu|join:'+'}} # safe:告知Django這段程式碼為安全的,不必進行轉義 {{ value|safe}}
4.2 標籤(tag)的使用
4.2.1 使用標籤的格式
- {% tags %}
4.2.2 常用的標籤
{% if %}
- {% if %} 標籤接受and,or或者not來測試多個變數值或者否定一個給定的變數
- {% if %} 標籤不允許同一標籤裡同時出現and和or
- {% if %} 可以和過濾功能進行配合
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大於200</p> {% else %} <p>num大於100小於200</p> {% endif %} {% elif num < 100%} <p>num小於100</p> {% else %} <p>num等於100</p> {% endif %}
{% for %}
<ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul> # 在標籤裡可以用reversed來反序迴圈列表 {% for obj in list reversed %} ... {% endfor %}
- forloop.first 第一次迴圈
- forloop.last 最後一次迴圈
- 示例:
{% for foo in name_list %} {% if forloop.first %} {{ foo }} {% else %} <p>只有第一次迴圈列印</p> {% endif %} {% endfor %}
{% csrf_token %}
- 用於生成csrf_token的標籤,用於防止跨站攻擊驗證
- 這裡其實會生成一個隱藏的input標籤,提交時和其他表達標籤一併提交給後臺
- 使用時在form標籤裡面加上{% csrf_token %}即可
<form action="{% url "xxoo" %}" > <input type="text"> <input type="submit"value="提交"> {% csrf_token %} </form>
{% url %}
- 用於引入路由配置的地址
# 給url匹配模式起名為 home,別名不需要改,路徑就可以隨便改了,別的地方要使用這個路徑,則用這個別名即可 url(r'^home', views.home, name='home'), # 在模板中的使用 {% url 'home' %} #模板渲染的時候,被django解析成了這個名字對應的那個url,這個過程叫做反向解析
{% with %}
- 用更簡單的變數名替代複雜的變數名
- 只在with段內有效
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
{% load %}
- 載入標籤庫
4.3 自定義filter和simple_tag
1)在app中建立templatetags模組(必須建立,且名字不能改)
2)建立 .py檔案,如my_tags.py
from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改變 @register.filter def filter_multi(v1,v2): return v1 * v2 @register.simple_tag def simple_tag_multi(v1,v2): return v1 * v2 @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg,) return mark_safe(result)
3)在settings中的INSTALLED_APPS配置當前app
- 要配置當前app,否則Django無法找到自定義的simple_tag
- 如果找不到,重啟一下Django試試
3)在使用自定義simple_tag和filter的html檔案中匯入之前建立的 my_tags.py :{% load my_tags %}
- 必須在模板的首行匯入{% load xxx %},這裡是匯入my_tags
4)使用simple_tag和filter
{% load xxx %} #首行 # num=12 {{ num|filter_multi:2 }} # filter_multi只能傳一個值,前面的num將作為它的第一個引數 # 而冒號後的值將作為第二個引數 {% simple_tag_multi 2 5 %} # 引數不限,但不能放在if for語句中 {% simple_tag_multi num 5 %} # filter_multi可以用在if等語句後,simple_tag不可以 {% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}
4.4 模板的繼承
1)include
- include標籤允許在(模板中)包含其它的模板的內容。
- 標籤的引數是所要包含的模板名稱,可以是一個變數,也可以是用單/雙引號硬編碼的字串。
- 每當在多個模板中出現相同的程式碼時,就應該考慮是否要使用{%include%}來減少重複
2)extends
- 繼承母版master.html,只需在其他頁面新增一行:
{% extends 'master.html' %}
3)block
- 對母版中對應位置的內容進行替換,一般對js,css,html三部分內容定義三個bock
- 在base模版中設定越多的
{% block %}
標籤越好 - 不能在一個模板中定義多個相同名字的block標籤
在母版中定義:
<div class="menu"> {% block content %} {% endblock %} </div>
在其他頁面對母版繼承後,再進行對應內容的替換:
{% extends master.html %} # 繼承母版 # 進行對應位置內容的替換 {% block content %} base頁面首頁 {% endblock %}
4)保留母版內容並新增新特性
- 使用super即可
母版html:
<div class="menu"> {% block content %} <div>這是母版測試頁面</div> {% endblock %} </div>
base.html:
{% block content %} {{ block.super }} base頁面首頁 {% endblock %}
5. Models(ORM單表操作)
ORM是 “物件-關係-對映” 的簡稱。(Object Relational Mapping,簡稱ORM)
5.1 資料庫的配置和使用
1)配置settings檔案
django預設使用sqlite的資料庫,並預設自帶sqlite的資料庫驅動
如果要更改資料庫為MySQL,需要配置如下:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'books', # 資料庫名稱,必須事先建立好 'USER': 'root', # 資料庫使用者名稱 'PASSWORD': '', # 資料庫密碼 'HOST': '', # 資料庫主機,留空預設為localhost 'PORT': '3306', # 資料庫埠 } }
2)更改MySQL驅動
django預設的MySQL驅動為MySQLdb,而MySQLdb在py3中有問題,所以還需要更改MySQL驅動為pymysql
# 找到專案名檔案下的__init__,在裡面寫入: import pymysql pymysql.install_as_MySQLdb()
3)在models中通過類建立資料庫表
在對應app的models檔案中建立資料庫表
- 每個類就對應一張表
- 類的每個例項就對應於表中的一條記錄
- 每個類中的屬性就對應每張表中對應的每個欄位
from django.db import models # Create your models here. class UserInfo(models.Model): # 這裡類就對應於一張表,且必須繼承models.Model id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) age = models.IntegerField() current_date = models.DateField() """ 上面的幾個類的屬性通過ORM對映就對應成了: create table userinfo( id int primary key auto_increment, name varchar(16), age int, current_date date) """
4)在資料庫中生成表結構
將上面的類生成真生的資料庫中的表結構
python manage.py makemigrations # Django 會在相應的 app 的migrations資料夾下面生成 一個python指令碼檔案 python manage.py migrate # 生成資料庫表 # 此時,對應app下面的migrations目錄中出現一個0001_initial.py的檔案,這個檔案就是執行了上述指令之後產生的指令碼檔案,這個檔案就是一個記錄
5.2 更多的欄位和引數
5.2.1 欄位
CharField # 字串欄位, 用於較短的字串 # CharField 必須有一個引數 maxlength, 限制該欄位所允許的最大字元數. IntegerField # 用於儲存一個整數 DecimalField # 一個浮點數. 必須 提供兩個引數: # max_digits 總位數(不包括小數點和符號) # decimal_places 小數位數 # 要儲存最大值為 999 (小數點後儲存2位): # models.DecimalField(..., max_digits=5, decimal_places=2) # 要儲存最大值一百萬(小數點後儲存10位): # models.DecimalField(..., max_digits=17, decimal_places=10) # max_digits大於等於17就能儲存百萬以上的數了 # admin 用一個文字框(<input type="text">)表示該欄位儲存的資料 AutoField # 一個 IntegerField, 新增記錄時它會自動增長,通常不需要直接使用這個欄位 # 自定義一個主鍵:my_id=models.AutoField(primary_key=True) # 如果不指定主鍵,系統會自動新增一個主鍵欄位到 model BooleanField # A true/false field # admin 用 checkbox 來表示此類欄位 TextField # 一個容量很大的文字欄位 # admin 用一個 <textarea> (文字區域)表示該欄位資料.(一個多行編輯框) EmailField # 一個帶有檢查Email合法性的 CharField,不接受 maxlength 引數 DateField # 一個日期欄位 # 有下列額外的可選引數: # auto_now # 當物件被儲存時(更新或者新增),自動將該欄位的值設定為當前時間. # 通常用於表示 "last-modified" 時間戳. # auto_now_add # 當物件首次被建立時,自動將該欄位的值設定為當前時間. # 通常用於表示物件建立時間. # (僅僅在admin中有意義...) DateTimeField # 一個日期時間欄位. 類似 DateField 支援同樣的附加選項 ImageField # 類似 FileField, 不過要校驗上傳物件是否是一個合法圖片 # 它有兩個可選引數:height_field和width_field,如果提供這兩個引數,則圖片將按提供的高度和寬度規格儲存 FileField # 一個檔案上傳欄位. # 要求一個必須有的引數: upload_to, 一個用於儲存上載檔案的本地檔案系統路徑. # 這個路徑必須包含 strftime #formatting, # 該格式將被上載檔案的 date/time替換(so that uploaded files don't fill up the given directory). # admin 用一個<input type="file">部件表示該欄位儲存的資料(一個檔案上傳部件) . # # 在一個 model 中使用 FileField 或 ImageField 需要以下步驟: # 1) 在 settings 檔案中, 定義一個完整路徑給 MEDIA_ROOT 以便讓 Django在此處儲存上傳檔案 # 出於效能考慮,這些檔案並不儲存到資料庫 # 定義MEDIA_URL 作為該目錄的公共 URL. 要確保該目錄對WEB伺服器使用者帳號是可寫的. # 2) 在 model 中新增 FileField 或 ImageField, 並確保定義了 upload_to 選項, # 以告訴 Django使用 MEDIA_ROOT 的哪個子目錄儲存上傳檔案. # 資料庫中要儲存的只是檔案的路徑(相對於 MEDIA_ROOT). # 如果 ImageField 叫作 mug_shot, 就可以在模板中以 {{ object.#get_mug_shot_url }} 這樣的方式得到影象的絕對路徑 URLField # 用於儲存 URL. # 若 verify_exists 引數為 True (預設), 給定的 URL 會預先檢查是否存在( 即URL是否被有效裝入且沒有返回404響應). # admin 用一個 <input type="text"> 文字框表示該欄位儲存的資料(一個單行編輯框) NullBooleanField # 類似 BooleanField, 不過允許 NULL 作為其中一個選項. # 推薦使用這個欄位而不要用 BooleanField 加 null=True 選項 # admin 用一個選擇框 <select> (三個可選擇的值: "Unknown", "Yes" 和 "No" ) 來表示這種欄位資料 XMLField # 一個校驗值是否為合法XML的 TextField # 必須提供引數: schema_path, 它是一個用來校驗文字的 RelaxNG schema 的檔案系統路徑. FilePathField # 可選專案為某個特定目錄下的檔名. # 支援三個特殊的引數, 其中第一個是必須提供的.這三個引數可以同時使用. # path # 必需引數. 一個目錄的絕對檔案系統路徑. FilePathField 據此得到可選專案. # Example: "/home/images". # match # 可選引數. 一個正則表示式, 作為一個字串, FilePathField 將使用它過濾檔名. # 注意這個正則表示式只會應用到 base filename 而不是路徑全名. # Example: "foo.*\.txt^", 將匹配檔案 foo23.txt 卻不匹配 bar.txt 或 foo23.gif. # recursive # 可選引數.要麼 True 要麼 False. 預設值是 False. 是否包括 path 下面的全部子目錄. # # match 僅應用於 base filename, 而不是路徑全名 # FilePathField(path="/home/images", match="foo.*", recursive=True) # 會匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif IPAddressField # 一個字串形式的 IP 地址, (i.e. "24.124.1.30"). CommaSeparatedIntegerField # 用於存放逗號分隔的整數值. 類似 CharField, 必須要有maxlength引數.
5.2.2 引數
null # 如果為True,Django 將用NULL 來在資料庫中儲存空值,預設值是 False. blank # 如果為True,該欄位允許不填。預設為False。 # 這與 null 不同。null純粹是資料庫範疇的,而 blank 是資料驗證範疇的。 # 如果一個欄位的blank=True,表單的驗證將允許該欄位是空值。如果欄位的blank=False,該欄位就是必填的。 default # 欄位的預設值。可以是一個值或者可呼叫物件。如果可呼叫 ,每有新物件被建立它都會被呼叫 # 如果欄位沒有設定可以為空,將來如果後新增一個欄位,這個欄位就要給一個default值 primary_key # 如果為True,那麼這個欄位就是模型的主鍵。 # 如果沒有指定任何一個欄位的primary_key=True,Django會自動新增一個IntegerField欄位做為主鍵 # 所以除非想覆蓋預設的主鍵行為,否則沒必要設定任何一個欄位的primary_key=True。 unique # 如果該值設定為 True, 這個資料欄位的值在整張表中必須是唯一的 choices # 由二元組組成的一個可迭代物件(例如,列表或元組),用來給欄位提供選擇項 # 如果設定了choices ,預設的表單將是一個選擇框而不是標準的文字框, # 而且這個選擇框的選項就是choices 中的選項 db_index # 如果db_index=True 則代表著為此欄位設定資料庫索引 DatetimeField、DateField、TimeField 這個三個時間欄位,都可以設定如下屬性: auto_now_add # 配置auto_now_add=True,建立資料記錄的時候會把當前時間新增到資料庫。 # auto_now # 配置上auto_now=True,每次更新資料記錄的時候會更新該欄位,標識這條記錄最後一次的修改時間
5.3 增:新增表記錄
1)方式一
在Views的index函式中操作:
def index(request): # 例項化一個物件就是一條記錄 student_obj = models.Student( name='hgzero', age=18 ) student_obj.save() # 將此記錄增加到資料表中 return render(request,'index.html')
2)方式二
通過objects控制器物件來呼叫資料表相應的增刪改查方法。
它可以建立一個新物件儲存到對應的資料表中,並返回這個新建立的物件。
這個models類的物件就稱之為model物件。
new_obj = models.Student.objects.create( name='hgzero', age=19 ) print(new_obj) # Student object print(new_obj.name) # hgzero
3)方式三:批量建立
批量插入很多資料:
obj_list = [models.Student(name=f'stu{i}', age=20) for i in range(1, 21)] models.Student.objects.bulk_create(obj_list) # 呼叫bulk_create來批量插入資料
5.4 查:獲取行記錄
1)all() 全部取出
- 通過 objects 控制器呼叫,返回QuerySet型別,裡面有很多個Student類的物件也就是model物件
- QuerySet類似於列表,可以迴圈遍歷取值
all_objs = models.Student.objects.all() ''' < QuerySet[ < Student: Student object >, < Student: Student object >, < Student: Student object >, ...'...(remaining elements truncated)...' ]> '''
2)filter(條件) 條件查詢
- 通過object控制器呼叫,返回QuerySet型別
- 如果查詢不到內容不會報錯,返回一個空的QuerySet集合
objs = models.Student.objects.filter(id=2) objs = models.Student.objects.filter(name='xxx', age=18) # 多條件查詢 print(objs) # <QuerySet [<Student: hgzero>]> print(objs[0].id) # 可以通過索引取值
3)get(條件) 條件查詢
- 通過object控制器呼叫,返回model物件
- 通過get條件查詢,查詢的結果有且只有1個
obj = models.Student.objects.get(id=1) # 返回的是model物件,且查詢結果只能有一個
4)exclude 排除
- 通過object物件或者QuerySet集合呼叫,返回QuserySet集合
# 排除name為hgzero的行記錄,將剩下所有的返回 objs = models.Student.objects.filter(age=20).exclude(name='hgzero')
5)order_by 排序
- 通過object物件或者QuerySet集合呼叫,返回QuserySet集合
# object物件呼叫 objs = models.Student.objects.order_by('age') # 通過姓名升序排列 # queryset集合呼叫 objs = models.Student.objects.all().order_by('age') # 通過姓名升序排列
6)reverse 反轉
- 通過order_by返回的QuerySet集合呼叫,返回一個QuerySet集合
# 只能通過order_by返回的QuerySet集合呼叫 objs = models.Student.objects.order_by('id').reverse()
7)count 計數
- 通過QuerySet集合呼叫,返回一個元素個數
num = models.Student.objects.all().count() # 返回的是記錄的條數 num = models.Student.objects.filter(age=20).count()
8)first 返回第一個model物件
- 通過QuerySet集合呼叫,返回第一個model物件
obj = models.Student.objects.filter(age=20).first()
9)last 返回最後一個model物件
- 通過QuerySet集合呼叫,返回最後一個model物件
obj = models.Student.objects.filter(age=20).last()
10)exists 判斷是否存在
- 通過QuerySet集合呼叫,返回bool值
flag = models.Student.objects.filter(age=25).exists()
11)values_list
- 通過QuerySet集合呼叫,返回一個QuerySet集合
- 這個QuerySet裡面的元素是元組的形式,而不是model物件
query_tuple = models.Student.objects.filter(age=20).values_list() # <QuerySet [(4, 'stu1', 20), (24, 'stu2', 20), (27, 'stu3', 20)]> query_tuple = models.Student.objects.filter(age=20).values_list('name','age') # 指定想要獲取的欄位
12)values
- 通過QuerySet集合呼叫,返回一個QuerySet集合
- 這個QuerySet集合裡面是字典的形式,而不是model物件
query_dict = models.Student.objects.filter(age=19).values() # <QuerySet [{'id':3, 'name':'stu1', 'age':19}, {'id':25, 'name':'stu2', 'age':19}]> query_dict = models.Student.objects.filter(age=19).values('name', 'age') # <QuerySet [{'name':'stu1', 'age':19}, {'name':'stu2', 'age':19}]>
13)distinct 去重
- 通過QuerySet集合呼叫,返回一個QuerySet集合
- 對整個物件去重是沒有意義的,因為只要有一個欄位不同,都不是重複的
query_objs = models.Student.objects.filter(age=20).distinct() query_objs = models.Student.objects.filter(age=20).values('age').distinct() # 去重一般都用於values或者values_list
14)雙下劃線模糊查詢
query_objs = models.Student.objects.filter(age__gt=19) # 大於 query_objs = models.Student.objects.filter(age__gte=19) # 大於等於 query_objs = models.Student.objects.filter(age__lt=20) # 小於 query_objs = models.Student.objects.filter(age__lte=20) # 小於等於
query_objs = models.Student.objects.filter(age__range=[18, 20]) # 範圍 左右都包含 query_objs = models.Student.objects.filter(name__contains='xiao') # 針對字串型別,內容含有 query_objs = models.Student.objects.filter(name__icontains='xiao') # 針對字串型別,內容含有 不區分大小寫 query_objs = models.Student.objects.filter(name__startswith='x') # 匹配以x開頭 query_objs = models.Student.objects.filter(name__istartswith='x') # 匹配以x開頭,不區分大小寫 query_objs = models.Student.objects.filter(name__endswith='o') # 匹配以x結尾 query_objs = models.Student.objects.filter(name__iendswith='o') # 匹配以x結尾,不區分大小寫
15)日期
建立日期欄位:
class Birthday(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) date = models.DateField()
插入日期資料:
models.Birthday.objects.create(name='stu1', date='2020-06-28') models.Birthday.objects.create(name='stu2', date='2020-07-02')
查詢2020年6月出生的人:
query_objs = models.Birthday.objects.filter(date__year='2020',date__month='06') print(query_objs) # <QuerySet [<Birthday: stu1>]>
5.5 刪:刪除行記錄
1)呼叫model物件刪除
models.Student.objects.get(id=20).delete()
2)呼叫QuerySet集合刪除
models.Student.objects.filter(age=20).delete()
5.6改:更新行記錄
count = models.Student.objects.filter(name='stu1').update(age=20)
6. Models(ORM多表操作)
6.1 多對多表的建立方式
1)自行建立第三張表
class Book(models.Model): title = models.CharField(max_length=32, verbose_name="書名") class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") # 自己建立第三張表,分別通過外來鍵關聯書和作者 class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book")
2)通過ManyToManyField自動建立
class Book(models.Model): title = models.CharField(max_length=32, verbose_name="書名") # 通過ORM自帶的ManyToManyField自動建立第三張表 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") books = models.ManyToManyField(to="Book", related_name="authors") #自動生成的第三張表我們是沒有辦法新增其他欄位的