在腳本中如何進行Django的運行
if __name__ == '__main__':
import os
import django
# 注意路徑(當前所在的位置,要加載Django的配置文件)
os.environ.setdefault("DJANGO_SETTINGS_MODULE","orm69.settings")
django.setup()
# 進行的操做
一.搭建環境
設置pip install 的源
建立虛擬環境
mkvirtualenv py6_django -p python3
查看當前目錄下的虛擬環境
workon
設置Django的版本
pip install django==1.11.11
# 虛擬環境的指令
mkvirtualenv # 建立虛擬環境
rmvirtualenv # 刪除虛擬環境
workon # 進入虛擬環境、查看全部虛擬環境
deactivate # 退出虛擬環境
ctrl + h 查看隱藏文件
# pip
pip install # 安裝依賴包
pip uninstall # 卸載依賴包
pip list # 查看已安裝的依賴包
pip freeze # 凍結當前環境的依賴包
workon + py6_django 進入當前的虛擬環境
切換到桌面下的code中,將建立的項目放到裏面
cd ~/Desktop/code
django-admin startproject demo
查看樹狀圖
執行 tree,結果顯示以下的目錄結構
與項目同名的目錄,此處爲demo
settings.py 是項目的總體配置文件
urls.py 是項目的URL配置文件
wsgi.py 是項目與WSGI兼容的Web服務器入口
manage.py 是項目管理文件,經過它管理項目
運行開發服務器
python manage.py runserver
建立子應用(相似於藍圖)
python manage.py startapp testdatabase
執行 tree,結果顯示以下的目錄結構
admin.py 文件跟網站的後臺管理站點配置相關
apps.py 文件用於配置當前子應用的相關信息
migrations 目錄用於存放數據庫遷移歷史文件
models.py 文件用戶保存數據庫模型類
tests.py 文件用於開發測試用例,編寫單元測試
views.py 文件用於編寫Web應用視圖
建立完子應用時須要進行三個步驟:
第一步:設置路由
在工程配置文件settings.py中,INSTALLED_APPS項保存了工程中已經註冊安裝的子應用,
將剛建立的users子應用添加到工程中,可在INSTALLED_APPS列表中添加
'testdatabase.apps.TestdatabaseConfig'
第二步:在views中寫視圖函數
from django.http import HttpResponse
# 寫視圖函數時須要注意必需要傳request參數和返回一個HttpResponse的響應
def index(request):
"""
index視圖
:param request: 包含了請求信息的請求對象
:return: 響應對象
"""
return HttpResponse("hello world!")
第三步:在子應用中建立urls.py,保存子應用中的地址
在users/urls.py文件中定義路由信息
from django.conf.urls import url
from . import views
# urlpatterns是被django自動識別的路由列表變量
urlpatterns = [
# 每一個路由信息都須要使用url函數來構造
# url(路徑, 視圖)
# ^ / $ 需注意在子應用的urls.py中必定要有,
url(r'^index/$', views.index),
]
在該項目的(demo)urls.py中
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls), # django默認包含的
# 添加
# ^ / 需注意在子應用的urls.py中必定要有
url(r'^testdatabase/', include('testdatabase.urls')),
]
從新啓動django程序
python manage.py runserver
配置文件
BASE_DIR
DEBUG
將語言和時區修改成中國大陸信息
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
靜態文件
在項目根目錄下建立static_files目錄來保存靜態文件。
在demo/settings.py中修改靜態文件的兩個參數爲
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_files'),
]
此時在static_files添加的任何靜態文件均可以使用網址 /static/文件在static_files中的路徑來訪問了
用127.0.0.1:8000/static/index.html來訪問
注意:
Django 僅在調試模式下(DEBUG=True)能對外提供靜態文件,當DEBUG=False工做在生產模式時,Django再也不對外提供靜態文件,
須要是用collectstatic命令來收集靜態文件並交由其餘靜態文件服務器來提供
路由說明
路由定義位置
路由解析順序
從上至下
注意:須要注意定義路由的順序,避免出現屏蔽效應。
路由命名與reverse反解析(逆向)
路由信息
在定義路由的時候,能夠爲路由命名,方便查找特定視圖的具體路徑信息。
1) 在使用include函數定義路由時,可使用namespace參數定義路由的命名空間,如
url(r'^users/', include('users.urls', namespace='users')),
命名空間表示,凡是users.urls中定義的路由,均屬於namespace指明的users名下。
命名空間的做用:避免不一樣應用中的路由使用了相同的名字發生衝突,使用命名空間區別開。
2) 在定義普通路由時,可使用name參數指明路由的名字,如
urlpatterns = [
url(r'^index/$', views.index, name='index'),
url(r'^say', views.say, name='say'),
]
reverse反解析
使用reverse函數,能夠根據路由名稱,返回具體的路徑,如:
from django.core.urlresolvers import reverse # 注意導包路徑
def index(request):
return HttpResponse("hello the world!")
def say(request):
url = reverse('users:index') # 返回 /users/index/
print(url)
return HttpResponse('say')
對於未指明namespace的,reverse(路由name)
對於指明namespace的,reverse(命名空間namespace:路由name)
路徑結尾斜線的說明
Django中定義路由時,一般以斜線/結尾,其好處是用戶訪問不以斜線/結尾的相同路徑時,
Django會把用戶重定向到以斜線/結尾的路徑上,而不會返回404不存在。如
urlpatterns = [
url(r'^index/$', views.index, name='index'),
]
用戶訪問 index 或者 index/ 網址,均能訪問到index視圖。
說明:
雖然路由結尾帶/能帶來上述好處,可是卻違背了HTTP中URL表示資源位置路徑的設計理念。是否結尾帶/以所屬公司定義風格爲準。
請求和響應
請求
利用HTTP協議向服務器傳參有幾種途徑?
提取URL的特定部分,如/weather/beijing/2018,能夠在服務器端的路由中用正則表達式截取
查詢字符串(query string),形如key1=value1&key2=value2;
請求體(body)中發送的數據,好比表單數據、json、xml;
在http報文的頭(header)中
具體以下:
request
傳遞數據的方式
a、以查詢字符串的方式將參數放到了url中
http://127.0.0.1:8000/login?username=zhangsan&pwd=12345
b、將數據放到了請求體中
http://127.0.0.1:8000/login
c、路徑參數:將數據放到了路徑中
http://127.0.0.1:8000/login/zhangsan/123456
d、請求頭:將數據放到了請求頭中
URL路徑參數
未命名參數傳遞
url(r'^weather/([a-z]+)/(\d{4})/$', views.weather),
def weather(request, city, year):
print('city=%s' % city)
print('year=%s' % year)
return HttpResponse('OK')
命名參數按名字的傳遞
url(r'^weather/(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.weather),
def weather(request, year, city):
print('city=%s' % city)
print('year=%s' % year)
return HttpResponse('OK...')
Django中的QueryDict對象
定義在django.http.QueryDict
HttpRequest對象的屬性GET、POST都是QueryDict類型的對象與python字典不一樣,QueryDict類型的對象用來處理同一個鍵帶有多個值的狀況
方法get():根據鍵獲取值
若是一個鍵同時擁有多個值將獲取最後一個值,若是鍵不存在則返回None值,能夠設置默認值進行後續處理
dict.get('鍵',默認值)
可簡寫爲
dict['鍵']
方法getlist():根據鍵獲取值,值以列表返回,能夠獲取指定鍵的全部值,若是鍵不存在則返回空列表[],能夠設置默認值進行後續處理
dict.getlist('鍵',默認值)
查詢字符串Query String
獲取請求路徑中的查詢字符串參數(形如?k1=v1&k2=v2),能夠經過request.GET屬性獲取,
返回QueryDict對象
# /qs/?a=1&b=2&a=3
def qs(request):
a = request.GET.get('a')
b = request.GET.get('b')
alist = request.GET.getlist('a')
print(a) # 3
print(b) # 2
print(alist) # ['1', '3']
return HttpResponse('OK')
重要:查詢字符串不區分請求方式,即假使客戶端進行POST方式的請求,依然能夠經過request.GET獲取請求中的查詢字符串數據。
請求體
表單類型 Form Data
前端發送的表單類型的請求體數據,能夠經過request.POST屬性獲取,返回QueryDict對象
def get_body(request):
a = request.POST.get('a')
b = request.POST.get('b')
alist = request.POST.getlist('a')
print(a)
print(b)
print(alist)
return HttpResponse('OK')
非表單類型 Non-Form Data
非表單類型的請求體數據,Django沒法自動解析,能夠經過request.body屬性獲取最原始的請求體數據,本身按照請求體
格式(JSON、XML等)進行解析。request.body返回bytes類型。
例如要獲取請求體中的以下JSON數據
{"a": 1, "b": 2}
能夠進行以下方法操做:
import json
def get_body_json(request):
json_bytes = request.body
json_str = json_bytes.decode()
json_data = json.loads(json_str)
print(json_data['a'])
print(json_data['b'])
return HttpResponse('OK')
請求頭
經過request.META屬性獲取請求頭headers中的數據,request.META爲字典類型
常見的請求頭如:
CONTENT_LENGTH – The length of the request body (as a string).
CONTENT_TYPE – The MIME type of the request body.
HTTP_ACCEPT – Acceptable content types for the response.
HTTP_ACCEPT_ENCODING – Acceptable encodings for the response.
HTTP_ACCEPT_LANGUAGE – Acceptable languages for the response.
HTTP_HOST – The HTTP Host header sent by the client.
HTTP_REFERER – The referring page, if any.
HTTP_USER_AGENT – The client’s user-agent string.
QUERY_STRING – The query string, as a single (unparsed) string.
REMOTE_ADDR – The IP address of the client.
REMOTE_HOST – The hostname of the client.
REMOTE_USER – The user authenticated by the Web server, if any.
REQUEST_METHOD – A string such as "GET" or "POST".
SERVER_NAME – The hostname of the server.
SERVER_PORT – The port of the server (as a string).
具體使用如:
def get_headers(request):
print(request.META['CONTENT_TYPE'])
return HttpResponse('OK')
其餘經常使用HttpRequest對象屬性
method:一個字符串,表示請求使用的HTTP方法,經常使用值包括:'GET'、'POST'
user:請求的用戶對象
path:一個字符串,表示請求的頁面的完整路徑,不包含域名和參數部分
encoding:一個字符串,表示提交的數據的編碼方式,若是爲None則表示使用瀏覽器的默認設置,通常爲utf-8這個屬性是可寫的,能夠經過修改它來
修改訪問表單數據使用的編碼, 接下來對屬性的任何訪問將使用新的encoding值
FILES:一個相似於字典的對象,包含全部的上傳文件
響應
HttpResponse
可使用django.http.HttpResponse來構造響應對象。
HttpResponse(content=響應體, content_type=響應體數據類型, status=狀態碼)也可經過HttpResponse對象屬性來設置響應體、
響應體數據類型、狀態碼:
content:表示返回的內容。
status_code:返回的HTTP響應狀態碼。
content_type:指定返回數據的的MIME類型。
響應頭能夠直接將HttpResponse對象當作字典進行響應頭鍵值對的設置:
response = HttpResponse()
response['Itcast'] = 'Python' # 自定義響應頭Itcast, 值爲Python
示例:
from django.http import HttpResponse
def demo_view(request):
return HttpResponse('itcast python', status=400)
或者
response = HttpResponse('itcast python')
response.status_code = 400
response['Itcast'] = 'Python'
return response
HttpResponse子類
Django提供了一系列HttpResponse的子類,能夠快速設置狀態碼
HttpResponseRedirect 301
HttpResponsePermanentRedirect 302
HttpResponseNotModified 304
HttpResponseBadRequest 400
HttpResponseNotFound 404
HttpResponseForbidden 403
HttpResponseNotAllowed 405
HttpResponseGone 410
HttpResponseServerError 500
JsonResponse
若要返回json數據,可使用JsonResponse來構造響應對象,做用:
1)幫助咱們將數據轉換爲json字符串
2)設置響應頭Content-Type爲 application/json
from django.http import JsonResponse
def demo_view(request):
return JsonResponse({'city': 'beijing', 'subject': 'python'})
redirect重定向
from django.shortcuts import redirect
def demo_view(request):
return redirect('/index.html')
Cookie
Cookie的特色
Cookie以鍵值對的格式進行信息的存儲。
Cookie基於域名安全,不一樣域名的Cookie是不能互相訪問的,如訪問itcast.cn時向瀏覽器中寫了Cookie信息,使用同一瀏覽器訪問baidu.com時,
沒法訪問到itcast.cn寫的Cookie信息。當瀏覽器請求某網站時,會將瀏覽器存儲的跟網站相關的全部Cookie信息提交給網站服務器。
設置Cookie
能夠經過HttpResponse對象中的set_cookie方法來設置cookie。
HttpResponse.set_cookie(cookie名, value=cookie值, max_age=cookie有效期)
max_age 單位爲秒,默認爲None。若是是臨時cookie,可將max_age設置爲None。
代碼以下:
def demo_view(request):
response = HttpResponse('ok')
response.set_cookie('itcast1', 'python1') # 臨時cookie
response.set_cookie('itcast2', 'python2', max_age=3600) # 有效期一小時
return response
讀取Cookie
能夠經過HttpRequest對象的COOKIES屬性來讀取本次請求攜帶的cookie值。
request.COOKIES爲字典類型。
代碼以下:
def demo_view(request):
cookie1 = request.COOKIES.get('itcast1')
print(cookie1)
return HttpResponse('OK')
Session
啓用Session(Django默認啓用)
存儲方式
在settings.py文件中,能夠設置session數據的存儲方式,能夠保存在數據庫、本地緩存等
本地緩存
存儲在本機內存中,若是丟失則不能找回,比數據庫的方式讀寫更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存儲
優先從本機內存中存取,若是沒有則從數據庫中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
Redis
在redis中保存session,須要引入第三方擴展,咱們可使用django-redis來解決
安裝擴展
pip install django-redis
配置
在settings.py文件中作以下設置
"default" 只要兩次設置的名字同樣就能夠啦
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
若是redis的ip地址不是本地迴環127.0.0.1,而是其餘地址,訪問Django時,可能出現Redis鏈接錯誤
解決方法:
修改redis的配置文件,添加特定ip地址。
打開redis的配置文件
sudo vim /etc/redis/redis.conf
進行修改
在以下配置項進行修改(如要添加10.211.55.5地址)
bind 127.0.0.1 10.211.55.5
從新啓動redis服務
sudo service redis-server restart
Seesion操做
經過HttpRequest對象的session屬性進行會話的讀寫操做。
以鍵值對的格式寫session。
request.session['鍵']=值
根據鍵讀取值。
request.session.get('鍵',默認值)
清除全部session,在存儲中刪除值部分。
request.session.clear()
清除session數據,在存儲中刪除session的整條數據。
request.session.flush()
刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值。
del request.session['鍵']
設置session的有效期
request.session.set_expiry(value)
若是value是一個整數,session將在value秒沒有活動後過時。
若是value爲0,那麼用戶session的Cookie將在用戶的瀏覽器關閉時過時。
若是value爲None,那麼session有效期將採用系統默認值,默認爲兩週,
能夠經過在settings.py中設置SESSION_COOKIE_AGE來設置全局默認值。
類視圖
類視圖的好處:
1)代碼可讀性好
2)類視圖相對於函數視圖有更高的複用性,若是其餘地方須要用到某個類視圖的某個特定邏輯,直接繼承該類視圖便可
代碼以下:
在上面的子應用中
from django.views import View
def wrapper(func):
def inner(*args,**kwargs):
print("獲取頁面數據1")
ret = func(*args,**kwargs)
print("獲取頁面數據2")
return ret
return inner
class RegisterView(View):
@wrapper
def get(self,*args,**kwargs):
print("test get page")
return HttpResponse("get page")
def post(self,*args,**kwargs):
print("test post page")
return HttpResponse("post page")
urlpatterns = [
url(r"^register/$", views.RegisterView.as_view()),
]
中間件
中間件的定義方法
在testdatabase應用中新建一個middleware.py文件,
def my_middleware(get_response):
print('init 被調用')
def middleware(request):
print('before request 被調用')
response = get_response(request)
print('after response 被調用')
return response
return middleware
定義好中間件後,須要在settings.py 文件中添加註冊中間件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'testdatabase.middleware.my_middleware', # 添加中間件
]
定義一個視圖進行測試
def demo_view(request):
print('view 視圖被調用')
return HttpResponse('OK')
多箇中間件的執行順序
在請求視圖被處理前,中間件由上至下依次執行
在請求視圖被處理後,中間件由下至上依次執行
代碼以下:
定義兩個中間件
def my_middleware(get_response):
print('init 被調用')
def middleware1(request):
print('before request 被調用')
response = get_response(request)
print('after response 被調用')
return response
return middleware
def my_middleware2(get_response):
print('init2 被調用')
def middleware(request):
print('before request 2 被調用')
response = get_response(request)
print('after response 2 被調用')
return response
return middleware
註冊添加兩個中間件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'testdatabase.middleware.my_middleware1', # 添加中間件
'testdatabase.middleware.my_middleware2', # 添加中間件
]
執行結果爲:
init2 被調用
init 被調用
before request 被調用
before request 2 被調用
view 視圖被調用
after response 2 被調用
after response 被調用
數據庫
ORM的關係
一對多 ForeignKey 在多的一方設置外鍵
多對多 ManyToMany 通常設置在處理業務邏輯比較多的一方
配置
在settings.py中保存了數據庫的鏈接配置信息,Django默認初始配置使用sqlite數據庫。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
使用mysql數據庫
pip install PyMySQL
在Django的工程同名子目錄的__init__.py文件中添加以下語句
# 將PyMySQL裝飾成MySQLdb,方便Django識別
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
修改DATABASES配置信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 數據庫主機
'PORT': 3306, # 數據庫端口
'USER': 'root', # 數據庫用戶名
'PASSWORD': 'mysql', # 數據庫用戶密碼
'NAME': 'py6_django' # 數據庫名字
}
}
在MySQL中建立數據庫
create database py6_django default charset=utf8;
進行數據庫的遷移操做
遷移文件的生成
python manage.py makemigrations
同步到數據庫中
python manage.py migrate
若是不成功使用強制遷移
強制遷移
python manage.py migrate testdatabase --fake
查看MySQL數據庫日誌
......
tail -f /var/log/mysql/mysql.log # 能夠實時查看數據庫的日誌內容
利用ORM建立表並手動增長數據
# 添加數據
book = BookInfo(
btitle='西遊記',
bpub_date=date(1988, 1, 1),
bread=10,
bcomment=10)
book.save()
hero = HeroInfo(
hname="孫悟空",
hgender=0,
hcomment="七十二變",
hbook=book,
is_delete=0,
)
hero.save()
hero = HeroInfo(
hname="豬八戒",
hgender=0,
hbook_id=book.id,
is_delete=0,
)
hero.save()
HeroInfo.objects.create(
hname='沙悟淨',
hgender=0,
hbook=book
)
# 基本查詢
print(BookInfo.objects.all())
print(BookInfo.objects.get(btitle='雪山飛狐').id)
print(BookInfo.objects.get(id=3))
print(BookInfo.objects.get(pk=3))
# 將ID=3的排除,顯示其餘的
print(BookInfo.objects.exclude(id=3))
print(111111111)
try:
print(BookInfo.objects.get(id=12))
# except Exception as e:html
# 使用get獲取數據時,若是沒有回拋出異常前端
except BookInfo.DoesNotExist:
print("未找到對應的ID")
print(BookInfo.objects.count())
# 關於values的查詢
print("values".center(80,"*"))
print(BookInfo.objects.values("btitle","bpub_date"))
print("values_list".center(80,"#"))
print(BookInfo.objects.values_list("btitle","bpub_date"))
# 關於reverse的翻轉
print("reverse".center(80,"*"))
print(BookInfo.objects.all().reverse())
# 獲取最後一個數據
print("last".center(80,"#"))
print(BookInfo.objects.all().last())
# 獲取第一個數據
print("first".center(80,"*"))
print(BookInfo.objects.all().first())
# 判斷數據庫中是否有數據
print(BookInfo.objects.exists())
# 過濾查詢
# 表示判等
print(BookInfo.objects.filter(id__exact=1))
print(BookInfo.objects.filter(id=1)[0])
# 是否包含 contains
# 忽略大小寫 icontains
print(BookInfo.objects.filter(btitle__contains="西"))
#至關於between and 左右閉區間 1 <= ret <=5
print(BookInfo.objects.filter(id__range(1,5)))
print(BookInfo.objects.filter(btitle__startswith="雪"))
print(BookInfo.objects.filter(btitle__endswith="傳"))
# 時間和日期的查詢
print(BookInfo.objects.filter(bpub_date__year=1986))
print(BookInfo.objects.filter(bpub_date__gt=date(1986,1,1)))
# 空查詢
# 查詢書名不爲空的
print(BookInfo.objects.filter(btitle__isnull=False))
# 查詢書名爲空的
print(BookInfo.objects.filter(btitle__isnull=True))
# 範圍查詢
print(BookInfo.objects.filter(id__in=[1,2,3,5,7]))
# 比較查詢
print(BookInfo.objects.filter(id__gt=3))
print(BookInfo.objects.filter(id__gte=3))
print(BookInfo.objects.filter(id__lt=3))
print(BookInfo.objects.filter(id__lte=3))
# F對象(兩個字段做比較) -->橫向比較,能夠進行F(("bcomment")+1)*4操做
# 查詢閱讀量大於評論量的讀書
print(BookInfo.objects.filter(bread__gt=10)) # 閱讀量大於10
print(BookInfo.objects.filter(bread__gt=F("bcomment")))
# 查詢閱讀量大於2倍評論量的讀書
print(BookInfo.objects.filter(bread__gt=F("bcomment")*2))
# 給每本書加版本
print(BookInfo.objects.update(btitle=Concat(F("btitle"),Value("(初版)"))))
# Q對象 -->多個條件的 & | ~
# 查詢閱讀量大於20而且編號小於3
print(BookInfo.objects.filter(bread__gt=20,id__lt=3))
# 查詢閱讀量大於20,或者編號小於3
print(BookInfo.objects.filter(Q(bread__gt=20) | Q(id__lt=3)))
# 查詢編號不爲3的
print(BookInfo.objects.filter(~Q(id=3)))
# 聚合函數
# 查詢全部的閱讀數
print(BookInfo.objects.aggregate(get_sum = Sum("bread")))
# 查詢全部的書籍
print(BookInfo.objects.count())
# 分組查詢 annotate
books = BookInfo.objects.all().annotate(read = Count("bread"))
for book in books:
print(book.read)
# 排序
# 升序
print(BookInfo.objects.all().order_by("bread"))
# 降序
print(BookInfo.objects.all().order_by("-bread"))
# 關聯查詢
# 由一到多的訪問語法 -->一對應的模型類對象,多對應的模型類名小寫_set
book = BookInfo.objects.get(id=1)
print(book.heroinfo_set.all())
# 由多到一的訪問語法 -->多對應模型類對象,一對應模型類中的關係類屬性名
hero = HeroInfo.objects.get(id=1)
print(hero.hbook)
#訪問一對應的模型類關聯對象的id語法:多對應的模型類對象.關聯類屬性_id
hero = HeroInfo.objects.get(id=1)
print(hero.hbook_id)
# 關聯過濾查詢
# 由多模型類條件查詢一模型類數據:
# 語法以下:
# 關聯模型類名小寫__屬性名__條件運算符 = 值
# 注意:若是沒有 "__運算符"部分,表示等於
# 圖書英雄是孫悟空
print(BookInfo.objects.filter(heroinfo__hname="孫悟空"))
# 要求圖書中英雄的描述包含八
print(BookInfo.objects.filter(heroinfo__hname__contains="郭"))
# 由一模型類條件查詢多模型類數據:
# 語法以下:
# 一模型類關聯屬性名__一模型類屬性名__條件運算符=值
# 注意:若是沒有"__運算符"部分,表示等於
# 查詢書名爲天龍八部中的所欲英雄
print(HeroInfo.objects.filter(hbook__btitle="天龍八部"))
# 查詢閱讀量大於30的全部英雄
print(HeroInfo.objects.filter(hbook__bread__gt=30))python
# 修改
# 修改方法一:
# 具體的對象沒有updete方法.只有QuerySet對象纔有update方法
hero = HeroInfo.objects.get(hname='豬八戒')
hero.hname = '豬悟能'
hero.save()
# 修改方法二:
HeroInfo.objects.filter(hname='沙悟淨').update(hname='沙僧')
# 刪除
# 模型類對象.delete()
hero = HeroInfo.objects.get(id=13)
hero.delete()
# 模型類.objects.filter().delete()
HeroInfo.objects.filter(id=17).delete()
查詢集 QuerySet
概念:
Django的ORM中存在查詢集的概念。
查詢集,也稱查詢結果集、QuerySet,表示從數據庫中獲取的對象集合。
當調用以下過濾器方法時,Django會返回查詢集(而不是簡單的列表):
all():返回全部數據。
filter():返回知足條件的數據。
exclude():返回知足條件以外的數據。
order_by():對結果進行排序。
對查詢集能夠再次調用過濾器進行過濾,如
BookInfo.objects.filter(bread__gt=30).order_by('bpub_date')
也就意味着查詢集能夠含有零個、一個或多個過濾器.
過濾器基於所給的參數限制查詢的結果
從SQL的角度講,查詢集與select語句等價,過濾器像where、limit、order by子句。
判斷某一個查詢集中是否有數據:
exists():判斷查詢集中是否有數據,若是有則返回True,沒有則返回False。
兩大特性
惰性執行
緩存
限制查詢集
管理器Manager
概念:
管理器是Django的模型進行數據庫操做的接口,Django應用的每一個模型類都擁有
至少一個管理器。咱們在經過模型類的objects屬性提供的方法操做數據庫時,
便是在使用一個管理器對象objects。當沒有爲模型類定義管理器時,
Django會爲每個模型類生成一個名爲objects的管理器,它是models.Manager類的對象。
自定義管理器
咱們能夠自定義管理器,並應用到咱們的模型類上。
注意:一旦爲模型類指明自定義的過濾器後,Django再也不生成默認管理對象objects。
自定義管理器類主要用於兩種狀況:
1. 修改原始查詢集,重寫all()方法。
a)打開booktest/models.py文件,定義類BookInfoManager
#圖書管理器
class BookInfoManager(models.Manager):
def all(self):
#默認查詢未刪除的圖書信息
#調用父類的成員語法爲:super().方法名
return super().filter(is_delete=False)
b)在模型類BookInfo中定義管理器
class BookInfo(models.Model):
...
books = BookInfoManager()
c)使用方法
BookInfo.books.all()
2. 在管理器類中補充定義新的方法
a)打開booktest/models.py文件,定義方法create。
class BookInfoManager(models.Manager):
#建立模型類,接收參數爲屬性賦值
def create_book(self, title, pub_date):
#建立模型類對象self.model能夠得到模型類
book = self.model()
book.btitle = title
book.bpub_date = pub_date
book.bread=0
book.bcommet=0
book.is_delete = False
# 將數據插入進數據表
book.save()
return book
b)爲模型類BookInfo定義管理器books語法以下
class BookInfo(models.Model):
...
books = BookInfoManager()
c)調用語法以下:
book=BookInfo.books.create_book("abc",date(1980,1,1))
模板
1)配置文件
在工程中根目錄下建立模板目錄templates
在settings.py配置文件中修改TEMPLATES配置項的DIRS值
TEMPLATES = [
{
'DIRS': [os.path.join(BASE_DIR, 'templates')], # 此處修改
}
]
2)定義模板文件(index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ city }}</h1>
</body>
</html>
3)模板渲染
模板渲染須要三步
找到模板
定義上下文
渲染模板
第一種方法:
from django.http import HttpResponse
from django.template import loader, RequestContext
def index(request):
# 1.獲取模板
template=loader.get_template('testdatabase/index.html')
# 2.定義上下文
context={'city': '北京'}
# 3.渲染模板 # httpresponse返回的是一個含有HTML的字符串
return HttpResponse(template.render(context))
第二種方法:
from django.shortcuts import render
def index(request):
context={'city': '北京'}
return render(request,'index.html',context)
4)模板語法
模板變量
視圖函數代碼以下:
def index(request):
context = {
'city': '北京',
'adict': {
'name': '西遊記',
'author': '吳承恩'
},
'alist': [1, 2, 3, 4, 5]
}
return render(request, 'index.html', context)
# 前端代碼以下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ city }}</h1>
<h1>{{ adict }}</h1>
<h1>{{ adict.name }}</h1> 注意字典的取值方法
<h1>{{ alist }}</h1>
<h1>{{ alist.0 }}</h1> 注意列表的取值方法
</body>
</html>
模板語句
for循環
{% for item in 列表 %}
循環邏輯
{{forloop.counter}}表示當前是第幾回循環,從1開始
{%empty%} 列表爲空或不存在時執行此邏輯
{% endfor %}
if語句
{% if ... %}
邏輯1
{% elif ... %}
邏輯2
{% else %}
邏輯3
{% endif %}
注意:運算符左右兩側不能緊挨變量或常量,必須有空格。
{% if a == 1 %} # 正確
{% if a==1 %} # 錯誤
過濾器
語法以下:
變量|過濾器:參數
和flask同樣基本沒變化
註釋
單行註釋語法以下:
{#...#}
多行註釋使用comment標籤,語法以下:
{% comment %}
...
{% endcomment %}
模板繼承
只有繼承操做
{% extend "抽取的基類模板"%}
進行挖坑填坑操做
{% block 名稱 %}
#實際填充內容
{{ block.super }}用於獲取父模板中block的內容
{% endblock 名稱 %}
表單
form表單
非form表單
admin站點
使用Django的管理模塊,須要按照以下步驟操做:
1)管理界面本地化
在settings.py中設置語言和時區
LANGUAGE_CODE = 'zh-hans' # 使用中國語言
TIME_ZONE = 'Asia/Shanghai' # 使用中國上海時間
2)建立管理員
建立管理員的命令以下,按提示輸入用戶名、郵箱、密碼。
python manage.py createsuperuser
建立成功可訪問:
http://127.0.0.1:8000/admin/
3)註冊模型類
打開testdatabase/admin.py文件,編寫以下代碼:
from django.contrib import admin
from booktest.models import BookInfo,HeroInfo
admin.site.register(BookInfo)
admin.site.register(HeroInfo)
4)自定義管理頁面
具體看子應用testdabase的設置