Django基礎總結全
|
Django 基礎知識 |
|
Django入門知識 |
|
Conquering English is not different from conquering a great mountain,both of them requier determination stick and perseverance. ---------小尚不浪 |
目錄
第一章 認識django
1.1
第二章 URL視圖函數詳解
1.ur2詳解:
URL是Uniform Resource Locator的簡寫,統一資源定位符,
一個URL由以下幾部分組成:
***
python
scheme://host:port/path/?query_string=xxx #anchor
***
* scheme:代表的是訪問的協議,一般為http或者https以及ftp等。
* host:主機名,域名,比如www.baidu.com。
* port:端口號。當你訪問一個網站的時候,瀏覽器默認使用80端口。
* path:查找路徑。比如:www.baidu.com/trending/now,后面的trending/now就是path。
* query-string:查詢字符串,比如:www.baidu.com/s?wd=python,后面的wd=python就是查詢字符串。
* anchor:錨點,后臺一般不用管,前端用來做頁面定位的。
2 #運行項目:
1.通過pycharm的方式:文件->新建項目->選擇django。然后指定項目所在的路徑,
以及Python解釋器,再點擊Create就可以創建項目了。
2. pycharm:直接點擊右上角的綠色三角箭頭按鈕就可以了。
注意:用pycharm運行項目,要避免一個項目運行多次。
在項目配置中,把“只用單一實例”那個選項勾選上,避免同時運行多個項目。
3 #讓同局域網中的其他電腦訪向本機的項目:
1.在pycharm,右上角->項目配置->host。改成"0.0.0.0"。
2.在"settings.py"文件中,配置"ALLOWED_HOSTS",填入ip地址,或'*'(所有IP均可訪問)
***
ALLOWED_HOSTS =["161.171.0.121"]
ALLOWED_HOSTS =["*"]
***
注意:要關閉自己電腦的防火墻才行。|
4 #項目結構分析:
1."manage. py":以后和項目交互基本上都是基于這個文件。一般都是在終端輸入python manage.py [子命令]。
2."settings.py":保存項目所有的配置信息。
3."urls.py":用來做url與視圖函數映射的,以后來了請求就會從這個文件中找到匹配的視圖函數。
4."wsgi.py":專門用來做部署的。不需要修改。
5#django的項目app:
按照功能或者模塊進行分層,分成一個個app。所有和某個模塊相關的視圖都寫在對應的app的views.py中,并且模型和其他的也是類似。
然后django已經提供了一個比較方便創建app的命令叫做"python manage.py startapp + [app的名稱]"。
6# DEBUG模式:
1.如果開啟了DEBUG模式,那么以后我們修改了Django項目的代碼,然后按下ctrl+s,那么Django就會自動的給我們重啟項目,不需要手動重啟。
2.如果開啟了DEBUG模式,那么以后Django項目中的代碼出現bug了,那么在瀏覽pi器中和控制臺會打印出錯信息。
3.在生產環境中,禁止開啟DEBUG模式,不然有很大的安全隱患。
4.如果將DEBUG設置為False,那么必須要設置ALLOWED_HOSTS.
#t ALLOWED_HOSTS:
這個變量是用來設置以后別人只能通過這個變量中的Ip地址或者城名來進往訪問。|
7# 視圖函數:
1.視圖函數的第一個參數必須是request。
2.視圖函數的返回值必須是' django.http.response.HttpResponseBase '的子類的對象。
8# url映射補充:
1.去urls.py文件中尋找映射,是因為在"settings.py"文件中配置了"ROOT_URLCONF"為"urls.py",所有django會去"urls.py"中尋找。
2.在"urls.py"中我們所有的映射,都應該放在"urlpatterns"這個變量中。
3.所有的映射不是隨便寫的,而是使用"path"函數或者是"re_path"函數進行包裝的。
9# ur1傳參數給視圖函數:
1.采用在url中使用變量的方式:在path的第一個參數中,使用“<參數名>”的方式可以傳遞參數。然后在視圖函數中也要寫一個參數,
視圖函數中的參數必須和url中的參數名稱保持一致,不然就找不到這個參數。另外,url中可以傳遞多個參數。
2.采用查詢字符串的方式:在url中,不需要單獨的匹配查詢字符串的部分。只需要在視
圖函數中使用'request.GET.get("參數名稱")'的方式來獲取。示例代碼如下:
***
python
def author_detail(request):
author_id =request.GET['id^]
text='作者的id是:%s' % author_id
return HttpResponse(text)
***
因為查詢字符串使用的是“GET”請求,所以我們通過"request.GET.get('')"來獲取參數。并且因為"GET"是一個類似于字典的據類型,
所有獲取值的方式都是一樣的。
10# 內置url參數的轉換器:
from django.urls import converters(在urls中光標移至converters按下Ctrl+b即可查看顯示所有的轉換器及其類型)
1. str:除了斜杠'/'以外所有的字符都是可以的。
2. int:只有是一個或者多個的阿拉伯數字。
3. path:所有的字符都是滿足的。
4. uuid:只有滿足"uuid.uuid4()"這個函數返回的字符串的格式。
5. slug:英文中的模桿或者英文字符或者阿拉伯數字或者下劃線才滿足。
11# urls分層模塊化:
如果項目變得越來越大。那么url會變得越來越多。如果都放在主"urls.py"文件中,那么將不太好管理。
在app中新建一個urls.py文件用來存儲所有和這個app相關的子url。
注意:
1.應該使用"include"函數包含子"urls.py",并且這個"urls.py"的路徑是相對于項目的路徑。
示例代碼如下:
***
python
urlpatterns=[
path('admin/', admin.site.urls),
path('book', include('book.urls')),
]
***
2.在"app"的"urls.py"中,所有的ur1匹配要放在一個叫做"urlpatterns:"的變量中,否則找不到。
3."ur1"是會根據主"urls.py"和app中的"urls.py"進行拼接的,因此注意不要多加斜杠。
12# url命名:
1.為什么需要ur1命名?
因為url是經常變化的。如果在代碼中寫死可能會經常改代碼。給url取個名字,以后使用url的時候就使用他的名字進行反轉就可以了,
就不需要寫死url了。
2.如何給一個ur1指定名稱?
在"path"函數中,傳遞一個"name"參數就可以指定。示例代碼如下:
**python
urlpatterns =[
path("",views.index,name="index"),
path("login/',views.login,name='login')
]
#應用命名空間:
在多個app之間,有可能產生同名的url。這時候為了避免反轉url的時候產生混淆,可以使用應用命名空間,來做區分。
只要在“app"的"urls.py"中定義一個叫做"app_name"的變量,來指定這個應用的命名空間即可。
***python
app_name='front'
urlpatterns=[
path('',views.index,name='index'),
path('login/',views.login,name='login')
]
13#應用(app)命名空間和實例命名空間:
一個app,可以創建多個實例。可以使用多個url映射同一個app。所以這就會產生一個問題。以后在做反轉的時候,
如果使用應用命名空間,就混淆了。我們可以使用實例命名空間。
只要在"include"函數中傳遞一個"namespace"變量即可。示例代碼如下:
***python
urlpatterns = [
path('',include('front.urls')),
#同一app下有兩個實例
path('cms1/',include('cms.urls',namespace='cms1')),
path('cms2/',include('cms.urls',namespace='cms2')),
]
在做反轉的時候,可根據實例命名空間來指定具體的url。
***python
def index(request):
username=request.GET.get("username")
if username:
return HttpResponse('cms首頁')
else:
current_namespace=request.resolver_match.namespace
return redirect(reverse("%s:login"%current_namespace))
14# include函數的用法:
1. include(module,namespace=None):
* module:子url的摸塊字符串。
*namespace:實例命名空間。如果指定實例命名空間,那么
前提必須要先指定應用命名空間。在子"urls.py"中添加"app_name"變量。
2. include((pattern_list, app_namespace), namespace=None):"include"函數的第一
個參數既可以為一個字符串,也可以為一個元組,如果是元組,那么元組的第一個參數是
子"urls.py"模塊的字符串,元組的第二個參數是應用命名空間。應用命名空間既可以在子
"urls.py"中通過"app_name"指定,也可以在"include"函數中指定。
3. include(pattern_list):'pattern_list'是一個列表。這個列表中裝的是"path"或者"
re path"函數。實例代碼如下:
***python
path('movie/',include([
path('',views.movie),
path('list/',views.movie_list),
]))
15# re_path函數
1.re_path和path的作用都是一樣的。只不過"re_path"是在寫url的時候可以用正則表達式,功能更加強大。
2.寫正則表達式都推薦使用原生字符串。也就是以'r'開頭的字符串。
3.在正則表達式中定義變量,需要使用圈括號括起來。這個參數是有名字的,那么需要使用"?P<參數的名字>"。然后在后面添加正則表達式的規則。
***python
from django.urls import re_path
from.import views
urlpatterns =[
#r"":代表的是原聲字符串
re_path(r'^$',views.book),
#book/list/<year>/
re_path(r"^list/(?P<year>\d{4})/$",views.book_list),
re_path(r"^list/(?P<month>\d{2})/$",views.book_list_month)
]
16# reverse函數
1.在反轉url的時候,需添加參數,可以傳遞'kwargs'參數到'reverse'函數中。示例代碼如下:
***python
detail_url=reverse('detail',kwargs={"article_id":1,'page':2})
***
2.如果想添加查詢字符串的參數,則必須手動進行拼接,示例:
***python
login_url=reverse('login')+"?next=/"
***
17# 自定義url轉換器按照以下五個步驟來走就可以了:
1.定義一個類,直接繼承自object就可以了。
2.在類中定義一個屬性regex,這個屬性是用來限制ur1轉換器規則的正則表達式。
3.實現to_python(self,value)方法,這個方法是將url中的值轉換一下,然后傳給視圖函數的。
4.實現to_url(self,value)方法,這個方法是在做ur1反轉的時候,將傳進來的參數轉換后拼接成一個正確的url。
5.將定義好的轉換器,使用"django.url3.converters.register_converter"方法注冊到django中。
示例代碼如下:
***python
from django.urls import register_converter
class categoryConverter(object):
regex = r'\w+|(\w+\+\w+)+'
def to_python(self, value):
# python+django+flask
result = value.split("+")
# {'python','django','flast'}
return result
def to_url(self, value):
# value:{'python','django','flask'}
# python+django+flask
if isinstance(value, list):
result = "+".join(value)
return result
else:
raise RuntimeError("轉換參數的時候.必須為分類列表!")
register_converter(categoryConverter,'cate')
18# URL映射的時候指定默認參數:
可以指定默認參數,當訪問網頁時,因沒傳遞參數,默認匹配到第一個,在page函數中,可以指定傳遞第幾個參數。
示例代碼如下:
***python views函數
book_list=['三國演義','水滸傳','西游記','紅樓夢']
def books(request,page=0):
return HttpResponse(book_list[page])
#url函數中
urlpatterns=[
path('',views.books),
path('page/<int:page>/',views.books)
]
第三章模板
1# DTL與普通的HTML文件的區別:
DTL模板是一種帶有特殊語法的HTML文件,這個HTMHL文件可以被Django編譯,可以傳進參數進去,實現數據動態化。
在編譯完成后,生成一個普通的HTML文件,然后發送給客戶端。
#渲染模板:
渲染模板有多種方式。以下兩種常用的方式。
1)render_to_string:找到模板,然后將模板編譯后渲染成Python的字符串格式。最后再通過HttpResponse類
包裝成一個HttpResponse對象返回回去。示例代碼如下:
***python
from django.shortcuts import render
from django.template.loader import render_to_string
from django.http import HttpResponse
def index(request):
html=render_to_string("index.html")
return HttpResponse(html)
***
2) 直接將模板渲染成字符串和包裝成HttpResponse對象一步到位。
from django.shortcuts import render
def index(request):
return render(request,'index.html')
2 #模板變量
1.在模版中使用變量,需要將變量放到'{{變量}}'中。
2.如果想要訪問對象的屬性,那么可以通過'對象.屬性名'來進行訪問。
***python
class Person(object):
def __init__(self,username):
self.username=username
context={
'person':p
}
***
以后想要訪問'person'的'username',那么就是通過'person.username'來訪問。
3.如果想要訪問一個字典的key對應的value,那么只能通過'字典.key'的方式進行訪問。
***python
context={
'person':{
'username':'zhiliao',
}
}
以后在模板中訪問'username'。就是以下代碼'person.username'。
4.因為在訪問字典的'key'時候也是使用'點'來訪問,因此不能在字典中定義字典本身就有的屬性名當作'key',
否則字典的那個屬性將編程字典中的key了。
***python
context={
'person':{
'username':'zhiliao',
'keys':'abc'
}
}
***
以上因為將'keys'作為'person'這個字典的'key'了。因此以后在模版中訪問'person.keys'的時候,
返回的不是這個字典的所有key,而是對應的值。
5.如果想要訪問列表或者元組,通過'點.'的方式進行訪問,不能通過'中括號[]'的形式進行訪問。這一點和python中是不一樣的。
***python
{{ persons.0}}
3 #常用模板標簽
1.1 for...in...筆記:
'for...in...'標簽:'for...in...'類似于Python中的'for...in...'.可以遍歷列表、元組、字符串、字典等一切可以遍歷的對象。
***python
{% for person in persons %}
<li>{{ person.name }}</li>
{% endfor %}
1.2如果想要反向遍歷,那么在遍歷的時候就在'persons'后面加上一個'reversed'。
1.3遍歷字典的時候,需要使用'items'、'keys'和'values'等方法。在DTL中,執行一個方法不能使用圓括號的形式。
***python
{% for key,value in person.items %}
<li>{{ key }}/{{ value }}}</li>
{% endfor %}
2.在‘for’循環中,DTL提供了一些變量可供使用。這些變量如下:
2.1'forloop.counter':當前循環的下標,以1作為起始值。
2.2'forloop.counter0':當前循環的下標,以0作為起始值。
2.3'forloop.revcounter':反向下標元素。'forloop.revcountero':最后一個元素下標是0開始。
2.4'forloop.first':是否是第一次遍歷。
2.5'forloop.last':是否是最后一次遍歷。
2.6模板中的for...in...沒有continue和break語句,這一點和Python中有很大不同。
3.'for...in...empty'標簽:
這個標簽使用跟'for...in...'是一樣的,只不過是在遍歷的對象如果沒有元素的情況下,會執行'empty'中的內容。
***python
{% for comment in comments %}
<li>{{comment}}</li>
{% empty %}
<li>沒有任何評論</li>
{% endfor %}
4.with標簽
4.1在模板中,想要定義變量,可通過'with'語句來實現。
4.2'with'語句有兩種使用方式,第一種是'with xx=xxx'的形式,第二種是'with xx as xxx'的形式。
5. url標簽
5.1'url'標簽:在模版中,用'a'標簽中定義'href'屬性。
***python
<li><a href="/">首頁</a></li>
5.2如果'url'反轉的時候需要傳遞參數,那么可以在后面傳遞。但是參數分位置參數和關鍵字參數不能同時使用。
***python
# path部分
path('detail/<book_id>/',views.book_detail,name='detail')
# url反轉,使用位置參數
<a href="{% url 'book:detail' 1 %}">圖書詳情頁面</a>
# url反轉,使用關鍵字參數
<a href="{% url 'book:detail' book_id=1 %}">圖書詳情頁面</a>
5.3如果想要在使用'url'標簽反轉的時候要傳遞查詢字符串的參數,那么必須要手動在在后面添加。
***python
<a href="{% url 'login' %}?next=/">登錄</a>
5.4如果需要傳遞多個參數,那么通過空格的方式進行分隔。
***python
<a href="{% url 'detail' book_id='1' category='1' %}">最火的一篇文章</a>
6. spaceless 標簽:只移除html中的空白字符,不會移除標簽與文本之間的空白字符。包括空格、Tab鍵、換行等。
7. autoescape自動轉義
7.1 DTL中默認開啟自動轉義,會將特殊字符進行轉義。如將'<'轉義成'<'等。
7.2 如果變量確實是可信任的,可用'autoescape'標簽來關掉自動轉義。
***python
{% autoescape off %}
{{ info }}
{% endautoescape %}
8. verbatim 標簽:默認在'DTL'模板中是會去解析那些特殊字符的。'{% 和 %}'以及'{{'等。
***python
{% verbatim %}
{{if}}Still alive.{{/if}}
{% endverbatim %}
4 #常用過濾器(指函數)
為什么需要過濾器?
在DTL中,不支持函數的調用形式"()",不能傳遞參數。而過濾器就是一個函數,可以對需要處理的參數進行處理并
可額外接收一個參數(最多只能有兩個參數)。
1.add過濾器:將傳進來的參數添加到原來值上面,將'值'和'參數'轉換成整形相加。如果轉換失敗,進行拼接。
***python
def add_view(request):
context={
'value1':['1','2','3'],
'value2':['4','5','6']
}#輸出值為['1', '2', '3', '4', '5', '6']
return render(request,'add.html',context=context)
{{ value1|add:value2 }}
2.cut過濾器:移除值中所有指定字符串。
***python
{{ "hello world"|cut:" " }}#輸出值為helloworld
3.date過濾器:
***python
數據 context={
'today': datetime.now
}
模板 {{ today|date:"Y/m/d H:i:s" }}#將會輸出:'2021/12/09 22:54:06'
還有更多時間格式化的方式。見下表。
|Y|四位數字的年份|2018 |
|m|兩位數字的月份| 01-12 | |n|月份,1-9前面沒有0前綴| 1-12 |
|d|兩位數字的天| 01-31 | |j|天,但1-9前面沒有0前綴| 1-31 |
|g|小時,12小時格式的,1-9前面沒有0前綴| 1-12 |
|h|小時,12小時格式的,1-9前面有e前綴| 01-12 |
|G|小時,24小時格式的,1-9前面沒有0前綴| 1-23 |
|H|小時,24小時格式的,1-9前面有e前綴| 01-23 |
|i|分鐘,1-9前面有0前綴| 00-59 |
|s|秒,1-9前面有0前綴| 00-59 |
4.default:如果被評估為False。比如{}、""、None、[]等在這些if判斷中為False的值,都會使用default過濾器提供默認值。
***python
{{ value|default:"我是默認值" }}
default_if_none:只有在值為'None'時才會輸出提供的默認值。
5.first和last
first:返回列表/元組字符串/中的第一個元素。 {{ value|first }}
last:返回列表/元組字符串/中的最后第一個元素。 {{ value|last }}
6.floatformat
使用四舍五入的方式格式化一個浮點型。如果在過濾器沒有傳遞任何參數,那么只保留一位小數,可以傳遞一個參數,標識具體保留幾個小數。
***python
{{ value|floatformat:2 }} #保留兩位小數
7.striptags:刪除字符串所有的html標簽。
{{ value|striptags }} #如果value是'<script>alert("hello world")</script>'則輸出'alert("hello world")'
8.truncatechars如果給定字符超出過濾器指定長度。那么會進行切割,拼接為三個點來作為省略號。
{{ value|truncatechars:"5" }} #如果value值'為北京歡迎您~'呢么輸出結果是'北京歡迎...'三點為第五個字符。
truncatechars_html:不會省略標簽。
5 #自定義過濾器
1.首先在某個app中,創建一個python包,叫做'templatetags',這個包的名字必須為'templatetags',不然就找不到。
2.在這個'templatetags'包下面,創建一個python文件用來存儲過濾器。
3.在新建的python文件中,定義過濾器(也就是函數),這個函數的第一個參數永遠是被過濾的那個值,并且如果在使用過濾器的時候傳遞參數,
那么還可以定義另外一個參數。但是過濾器最多只能有2個參數。
4.在寫完過濾器(函數)后,要使用'django.template.Library.filter'進行注冊。
.5把這個過濾器所在的這個app添加到'settings.INSTALLED_APS'中,不然Django也找不到這個過濾器。
6.在模板中使用'load'標簽加載過濾器所在的python包。#{% load my_filter %}
7.'django.template.Library.filter'還可以當作裝飾器來使用。如果'filter'函數沒有傳遞任何參數,那么將會使用這個函數的名字來作為過濾器的
名字。當然如果你不想使用函數的名字來作為過濾器的名字,也可以傳遞一個'name'參數。
***python
@register.filter('my_greet')
def greet(value,word):
return value + word
6 #模板結構優化:
1.include:有些代碼是重復使用的,可單獨抽取出來,哪里需要直接使用'include'出來。
2.如果想要在'include'子模板傳遞參數,可使用'with xxx=xxx'的形式。
***python
{% include 'header.html' with username='小尚不浪' %}
3.模板繼承:在父模板中定義好一些變量和方法,然后在子類中實現,因為子模板肯定有自己不同的代碼,因此可以在父模板中定義一個'block'接口。
4.base模板:定義好一個'base.html',然后定義好兩個'block'接口,讓子模板根據具體來實現,子模板通過'extends'標簽來實現。
***html
{% extends 'base.html' %}
{% block content %}
<p>這是首頁的代碼</p>
{{ block.super }}
{% endblock %}
5.需要注意的是:extends標簽必須放在模版的第一行。
子模板中的代碼必須放在block中,否則將不會被渲染。
如果在某個'block'中需要使用父模版的內容,那么可以使用'{{block.super}}'來繼承。
7 #加載靜態文件
在DTL中,使用'static'標簽來加載靜態文件。要使用'static'標簽,首先需要'{% load static %}'。
1.首先確保'django.contrib.staticfiles'已經添加到'settings.INSTALLED_APPS'中。
2.確保在"settings.py"中設置了"STATIC_URL"。
3.在已經安裝了的'app'下創建一個文件夾叫做'static',然后再在這個'static'文件夾下創建一個當前'app'的名字的文件夾,
再把靜態文件放到這個文件夾下。例如你的'app'叫做'book',有一個靜態文件叫做'zhiliao.jpg',那么路徑為'book/static/book/
zhiliao.jpg'。直接把靜態文件放在'static'文件夾下,那么在模版加載靜態文件的時候就是使用'zhiliao.jpg',如果在多個'app'
之間有同名的靜態文件,這時候可能就會產生混淆。而在'static'文件夾下加了一個同名'app'文件夾,在模版中加載的時候就是使用'app/zhiliao.jpg',
這樣就可以避免產生混淆。)
4.如果有一些靜態文件是不和任何'app'掛鉤的。那么可以在"settings.py"中添加"STATICFILES_DIRS",以后'DTL'就會在這個列表的路徑中查找靜態文件。
例如可設置為:
***python
STATICFILES_DIRS =[
os.path.join(BASE_DIR,"static")
]
5.在模版中使用'load'標簽加載'static'標簽。比如要加載在項目的'static'文件夾下的'style.css'的文件。那么示例代碼如下:
***html
{% load static %}
<link rel="stylesheet" href="{% static 'style.css' %}">
6.如果不想每次在模版中加z載靜態文件都使用'load'加載'static'標簽,那么可以在"settings.py"中的"TEMPLATES/OPTIONS"添加
'builtins':['django.templatetags.static'],這樣以后在模版中就可以直接使用'static'標簽,而不用手動的'load'了。
第四章 數據庫
1 #Python DB API下規范下cursor對象常用接口:
1.description :如果 cursor 執行了查詢的 sql 代碼,那么讀取 cursor.description 屬性的時候,將返回一個列表,這個列表
中裝的是元組,元組中裝的分別是(name,type_code,display_size,internal_size,precision,scale,mull_ok),其中 name
代表的是查找出來的數據的字段名稱。
2.rowcount :代表的是在執行了 sql 語句后受影響的行數。
3.close:關閉游標。關閉游標以后就再也不能使用了,否則會拋出異常。
4. execute(sql[,parameters]):執行某個 sql 語句。如果在執行 sql 語句的時候還需要傳遞參數,那么可以傳給 parameters 參
數。示例代碼如下:
cursor.execute("select * from article where id=%s",(1,))
5.fetchone :在執行了查詢操作以后,獲取第一條數據。
6.fetchmany(size):在執行查詢操作以后,獲取多條數據。具體是多少條要看傳的 size 參數。如果不傳 size 參數,那么默認是獲取第一條數據。
7.fetchall :獲取所有滿足 sq1 語句的數據。
*{
margin: 0; #設置瀏覽器默認外邊距
padding: 0; #內邊距
}
.nav{
background: #3a3a3a;#背景顏色
height: 65px; #字體高度
overflow: hidden; #清除浮動,把字體設置在同一行
}
.nav li{
float: left; #左浮動
list-style: none; #列表風格
margin: 0 20px; 標簽間距
line-height: 65px;# 使li標簽處于居中
}
.nav li a{
color: #fff; #字體顏色
text-decoration: none; #下劃線
}
.nav li a:hover{
color: lightblue; #將鼠標放置標簽上的顏色
}
2 #ORM模型介紹:
隨著項目越來越大,采用寫原生SQL的方式在代碼中會出現大量的SQL語句:
1.SQL語句重復利用率不高,越復雜的SQL語句條件越多,代碼越長。會出現很多相近的SQL語句。
2.很多SQL語句是在業務邏輯中拼出來的,如果有數據庫需要更改,就要去修改這些邏輯,這會很容易漏掉對某些SQL語句的修改。
3.寫SQL時容易忽略web安全問題,給未來造成隱患。SQL注入。
4.ORM,全稱Object Relational Mapping,中文叫做對象關系映射,通過ORM我們可以通過類的方式去操作數據庫,而不用再寫原生的SOL語句。
通過把表映射成類,把行作實例,把字設作為尾性,ORM在執行對象操作的時候最終還是會把對應的操作轉換為數據庫原生語句。使用ORM有許多優點:
4.1易用性:使用ORM做數據庫的開發可以有效的減少重復SQL語句的概率,寫出來的模型也更加直觀、清晰。
4.2性能損耗小:ORM轉換成底層數據庫操作指令確實會有一些開銷。但從實際的情況來看,這種性能損耗很少(不足5%),只要
不是對性能有嚴苛的要求,綜合考慮開發效率、代碼的閱讀性,帶來的好處要遠遠大于性能損耗,而且項目越大作用越明顯。
4.3設計靈活:可以輕松的寫出復雜的查詢。
5.可移植性:Django封裝了底尾的數據庫實現,支持多個關系齡據庫引整,包括流行的MySOL、PostgresOL 和 SQLite 。
OOP(模型) ORM(庫) RDB(數據庫)
3 #映射模型到數據庫中:
將 ORM 模型映射到數據庫中。
1.在 settings.py 中,配置好 DATABASES ,做好數據庫相關的配置。
2.在 app 中的 models.py 中定義好模型,這個模型必須繼承自 django.db.models 。
3.將這個 app 添加到 settings.py 的 INSTALLED_APP 中。
4.在命令行終端,進入到項目所在的路徑,然后執行命令 python manage.py makemigrations 來生成遷移腳本文件。
5.同樣在命令行中,執行命令 python manage.py migrate 來將遷移腳本文件映射到數據庫中。
4 #ORM對數據庫的基本操作:
1.添加數據:
先用ORM創建一個對象,再用save保存就可以了。
**python
book = Book(name=‘西游記',author='吳承恩',price=100)
book.save()
2.查找數據:
所有的查找工作都是使用模型上的'objects'屬性來完成的。當然也可以自定義查詢對象。
2.1根據主鍵進行查找:使用主鍵進行查找。可以使用'objects.get(pk=xx)'方法。
**python
book = Book.objects.get(pk=1)
2.2根據字段進行查找:可以使用'objects.filter(name=xx)'方法進行查找。
**python
books = Book.objects.filter(name='三國演義').first()
使用'filter'方法返回來的是一個'QuerySet'對象。使用這個對象的'first'方法來獲取第一個值。
3.刪除數據:
首先查找到對應的數據模型。然后再執行這個模型的'delete'方法即可刪除。
**python
book = Book.objects.get(pk=1)
book.delete()
4.修改數據:
首先查找到對應的數據模型。然后修改這個模型上的屬性的值。再執行'save'方法即可修改完成。
**python
book=Book.objects.get(pk=1)
book.price=200
book.save()
5 #ORM常用Field詳解:
1.1 django.utils.timezone.now方法:
會根據'settings.py'中是否設置了'USE_TZ=True':獲取當前的時間。設置了可獲取一個'aware'類型的'UTC'時間。
如果沒有設置,那么就會獲取一個'navie'類型的時間。
1.2 django.utils.timezone.localtime方法:
會根據'setting.py'中的'TIME_ZONE'來將一個'aware'類型的時間轉換為'TIME_Z0NE'指定時區的時間。
2.DateField 日期類型:
在Python中是'datetime.date'類型,可以記錄年月日。在映射到數據庫中也是'date'類型。使用這個'Field'可以傳遞以下幾個參數:
2.1'auto_now':在每次這個數據保存的時候,都使用當前的時間。
2.2'auto_now_add':在每次數據第一次被添加進去的時候,都使用當前的時間。
3.DateTimeField 日期時間類型:
不僅可以存儲日期,還可以存儲時間。映射到數據庫中是'datetime'類型。這個'Field'也可以使用'auto_now'和'auto_now_add'兩個屬性。
4.TimeField 時間類型:
在數據庫中是'time'類型。在Python中是'datetime.time'類型。
5.EmailField:
類似于'CharField'。在數據庫底層也是一個“varchar'類型。最大長度是254個字符。
6.FileField:用來存儲文件的。
7.ImageField:用來存儲圖片文件的。
8.FloatField:浮點類型。映射到數據庫中是'float'類型。
9.IntegerField:整形。值的區間是'-2147483648—2147483647'。
10.BigIntegerField:大整形。值的區間是'-9223372036854775898—-9223372036854775807'。
11.PositiveSame11IntegerField:正整形。值的區間是'θ—2147483647'。
12.TextField:大量的文本類型。映射到數據庫中是longtext類型。
13.UUIDField:只能存儲'uuid'格式的字符串。'uuid'是一個32位的全球唯一的字符串,一般用來作為主鍵。
14.URLField:類似于'CharField',只不過只能用來存儲'ur1'格式的字符串。并且默認的'max_length'是200。
6. #Field的常用參數:
1.null:如果將表設置為True,django將會在映射表指定為空。
2.blank:標識這個字段在表單驗證時是否為空。默認值是False。null是一個純數據庫級別的。blank是表單驗證級別的。
3.db.column:可設置這個字段數據庫的名字
如:db.column='author_age'
4.default:更改該字段的默認值。
5.primary_key:是否為主鍵。
6.unique:在表中這個字段的值是否唯一。一般是手機號或者郵箱。
7. #Meta類中常見配置:
1.db_table:這個模型映射到數據庫中的表名。如果沒指定,映射時會使用默認表名。
2.ordering:設置在提取數據的排序方式。
8. #外鍵和表關系:
1.class Foreignkey:這個參數是引用模型的。
2.to,on_delete,**options:這個參數是使用外鍵引用的模型數據被刪除了,如CASCADE、SET_NULL。
**
class User(models.Model):
username=models.CharField(max_length=20)
password=models.CharField(max_length=200)
class Article(models.Model):
title=models.CharField(max_length=100)
content=models.TextField()
author=models.ForeignKey("User",on_delete=models.CASCADE)
3.引用另一個的app的模型,在傳遞to參數時使用app.model_name進行指定。
如果模型的外鍵引用的是本身自己的模型,可將to改為self,或者這個模型的名字。
9. #外鍵刪除操作:
如果一個模型使用了外鍵。可以通過 on_delete 來指定。可以指定的類型:
1.CASCADE :級聯操作。如果外鍵對應的那條數據被刪除了,那么這條數據也會被刪除。
2.PROTECT :受保護。即只要這條數據引用了外鍵的那條數據,那么就不能刪除外鍵的那條數據。
3.SET_NULL :設置為空。如果外鍵的那條數據被刪除了,那么在本條數據上就將這個字段設置為空。如果設置這個選項,前提是要
指定這個字段可以為空,null=True。
4.SET_DEFAULT :設置默認值。如果外鍵的那條數據被刪除了,那么本條數據上就將這個字段設置為默認值。如果設置這個選項,前
提是要指定這個字段一個默認值。
5.SET():如果外鍵的那條數據被刪除了。那么將會獲取 SET 函政中的值來作為這個外鍵的值。 SET函數可以接收一個可以調用的
對象,如果是可以調用的對象,那么會將這個對象調用后的結果作為值返回回去。
6.DO_NOTHING :不采取任何行為。一切全看數據庫級別的約束。
10. #表關系 :表關系都是通過外鍵進行關聯的。三種表關系:一對一、一對多(多對一)、多對多。
一對多:
1.應用場景:比如文章和作者的關系。一個文章只能由一個作者編寫,但一個作者可以編寫多篇文章。
2.實現方式:一對多或多對一都是通過FroeignKey來實現的。示例如下:
class User(models.Model):
username=models.CharField(max_length=20)
password=models.CharField(max_length=200)
class Article(models.Model):
title=models.ChaeField(max_length=100)
context=models.TextField()
author=models.ForeignKey("frontuser.FrontUSer",on_delete=models.CASCADE)
調用函數,直接輸入 default_category可得到函數的內容
例:def default_category():
return Category.objects.get(pk=1)
那么以后給Article對象指定author,示例代碼如下:
article=Article(title='shang',content='111')
author=User(username='xiaoshang',password='111')
#通過python manage.py makemigrations和python manage.py migrate保存到數據庫中創建模型
author.save()
article.author=authorarticle.save()
如果想要獲取某個用戶下的所有文章,可通過article_set來實現。示例如下:
category=Category.object.first()
#獲取第一個用戶寫的所有文章
articles=category.article_set.all()
#first():獲取第一條文章 filter():獲取過濾文章 all():獲取所有文章
for article in articles:
print(article)
一對一:
1.在Django中一對一是通過OneToOneField來實現的。'OneToOneField'相當于一個外鍵,有一個“唯一的約束(unique key)”來實現一對一。
2.若想進行反向引用,可通過引用對象改名字小寫形式進行訪問。示例代碼如下:
***python
class FrontUser(models.Model):
username=models.CharField(max_length200)
class UserExtenbsion(models.Model):
school=models.CharField(max_length=100)
user=models.OneToOneField("FrontUser",on_delete.CASADE)
#通過userextension來訪問Userextension對象。
若不想使用默認的屬性名字,則可在user后面添加'related_name=extension'參數,則'FrontUser'可通過extension來直接訪問'Userextension'對象。
多對多:
1.應用場景:例如標簽和文章的關系,一篇文章可以有多個標簽,一個標簽有多篇文章。
2.實現方式:通過ManyToManyField來實現。示例代碼如下:
***python
class Tag(models.Model):
tag.models.CharField(max_length=100)
#可以通過related_name修改訪問屬性。
class Article(models.Model):
title.models.CharField(max_length=100)
context.models.TextField()
article.models.ManyToMany("Article",related_name='tags')
將文章添加到某個分類時的兩種方法:
1.使用'bulk=False' 例如:category.article_set.add(article,bulk=False) #注意add中對于‘多對多’沒有bulk屬性,不能使用bulk=False來添加文章。
2.在添加'category.article_set.add(article)'之前,先通過article.save()將article保存到數據庫中。
實際上是為多對多關系建立了一個中間表article_tag_articles,這個中間表分別定義了兩個外鍵,引用到'article'和'tag'兩張表的主鍵。
11 #查詢操作:
1.查詢條件:查詢操作是數據庫中一個非常重要的操作,一般使用filter、exclude、get三種方法。在ORM模型上使用field+_+condition的格式。
(1)操作數據庫可以不通過Navicat Premium,直接使用pychar來連接并使用。
點擊最右邊database(數據庫),打開數據源中的MySQL,進入配置MySQL頁面,輸入對應的數據庫名稱、用戶名和密碼(注:要跟你之前創建數據庫的配置來填),
最后再進test驗證是否成功。這樣就可以繼承Navicat Premium里面對應數據庫的內容。
(2)打開之前創建的表格,添加內容,按下Crtl+Enter后可將內容保存到數據庫中。
exact:
def inde(request):
#在windows操作系統上,mysql的排序規則是(collation),對于所有來說大小寫都是不敏感的
#在Linux操作系統上,mysql的排序規則是(collation),對于utf8_bin 來說,大小寫敏感。
article=Article.object.filter(id_exact=1) #_exact可以忽略不寫
print(article.query)
print(article)
#like和=:大部分情況下是一樣的,只有少數部分是代表不同的,
#exact和iexact:本質就是like和=的區別,exact會被翻譯為=,iexact會被翻譯為like。
article=Article。object.filter(id_iexact=1)
print(article.query)
print(article)
return HttpResponse("success")
浙公網安備 33010602011771號