哪些請求方式在請求地址的時候可以帶請求體?
只有PATCH、POST、PUT、DELETE訪問一個url地址時可以帶請求體
web框架和web服務器
web框架:flask Django
作用:
1.路由分發(根據url找到對應的處理函數)
2.調用處理函數進行業務處理。
web服務器 app.run()
作用:
1.解析請求報文,調用框架程序處理請求。
2.組織響應報文,返回內容給客戶端。
web框架學習方法
-
如何搭建工程程序
工程的組建
工程的配置
路由定義
視圖函數的定義
-
如何獲取請求數據(操作request對象)
-
如何構造響應數據(構造response對象)
-
如何使用中間層
請求鉤子
-
框架提供的其他功能組件
數據庫
模板
admin
Django簡介
Django的主要目的是簡便、快速的開發數據庫驅動的網站。強調代碼複用、快速開發和DRY(不要自己重複造輪子)原則。
特點
1.重量級框架
Django原生提供了衆多的功能組件,讓開發更簡便快速。
- 提供項目工程管理的自動化腳本工具
- 數據庫ORM支持(對象關係映射,英語Object Relational Mapping)
- 模板
- 表單
- Admin站點
- 文件管理
- 認證權限
- session機制
- 緩存
2.MVT開發模式
Model(模型)-View(視圖)-Template(模板)
Model,負責和數據庫交互,進行數據處理
View,用於接收請求,處理業務邏輯
Template,負責封裝構造要返回的html
其實和MVC框架一樣
Django框架環境安裝&項目創建
1)命令
mkvirtualenv name -p python3 # 創建虛擬環境
workon name # 進入虛擬環境
pip install django==1.11.11 # 安裝django
cd 目錄 # 切換目錄
django-admin startproject <項目名稱> # 創建項目
python manage.py startapp #創建子應用
2)進行子應用註冊
點開項目目錄下的settings,在INSTALLED_APPS中配置
3)啓動
python manage.py runserver
定義視圖函數
定義在子應用的views.py中
需要request接收請求並返回響應對象
def index(requset):
"""request:接收請求對象"""
# 返回相應對象
return HttpResponse('hello world')
URL配置
1) 在子應用中創建urls.py,設置子應用中url地址和視圖函數之間的對應關係
from django.conf.urls import url
from users import views
urlpatterns = [
# 添加當前子應用中url地址和視圖函數之間的對應關係
# url('地址url正則表達式','對應視圖函數')
url(r'index',views.index),
]
2)在項目總的urls.py文件中包含子應用中的urls.py文件
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 包含子應用中urls.py文件
url(r'^users/',include('users.urls'))
]
3)Django路由匹配過程說明
先找項目總的urls.py中正則匹配url地址,調用視圖函數,再進入子應用中的urls.py進行正則匹配,調用視圖函數
4) 路由配置時兩個注意點:
在子應用中進行url配置時,嚴格匹配開頭和結尾
Django url 地址配置的默認風格時:末尾加/
url(r'^index/$', views.index)
5)Django路由配置-url地址的反向解析
總的應用中定義別名用namespace=’’
url(r'^users/', include('users.urls', namespace='users')),
子應用中定義別名用name=’’
url(r'^index/$', views.index, name='index'),
根據視圖獲取對應的url地址,通常配合重定向進行使用。
def url_reverse(request):
# 獲取index視圖所對應的url地址
from django.urls import reverse
req_url = reverse('users:index')
return HttpResponse('OK')
配置文件settings.py
1)BASE_DIR(根目錄)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
2)DEBUG
- 修改代碼文件,程序自動重啓
- Django程序出現異常時,向前端顯示詳細的錯誤追蹤信息
3)中國語言與時區
在settings.py中配置
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
# LANGUAGE_CODE = 'en-us' # 設置語言
LANGUAGE_CODE = 'zh-Hans' # 設置語言
# TIME_ZONE = 'UTC' # 設置時區
TIME_ZONE = 'Asia/Shanghai' # 設置時區
4)靜態文件的使用
在settings.py中配置
1)設置訪問靜態文件路徑的前綴地址
2)指定Django中靜態文件存放的目錄
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
# 設置訪問靜態文件路徑的前綴地址
STATIC_URL = '/static/'
# 指定Django中靜態文件存放的目錄
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
請求參數傳遞
4種傳參方式
1.通過url地址傳遞參數(利用正則表達式提取參數的方法從url中獲取請求參數)
#/weather/城市名/年份/:比如:/weather/shanghai/2019/
#flask: 路由轉換器 /weather/<city>/<int:year>
#Django:
#未命名參數按定義順序傳遞,正則需要小括號括起來,分組
#在urls中配置正則
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')
#命名參數按名字傳遞
#在urls中配置正則 ?P給參數起別名
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')
2.請求參數傳遞(通過查詢字符串傳參)
# /qs/?a=1&b=2&c=3&c=4
# flask:request.args
def get_qs(request):
# 獲取查詢字符串的參數
a = request.GET.get('a')
b = request.GET.get('b')
c = request.GET.get('c') # ,如果c對應多個值,默認只查詢到最後一個值
clist = request.GET.getlist('c') # 使用此方法可以查詢c的列表
return HttpResponse('OK')
3.通過請求體傳遞參數(json數據或表單)
表單數據:/from_data/
request.POST:QueryDict類型的對象,允許一個鍵對應多個值
request.POST.get('name')
request.POST.get('age')
<from methods='get' action='提交地址'>
<input type='text' name='a'/>
<input type='text' name='b'/>
<input type='submit' value='提交'/>
</from>
json數據:/json_data/
request.body
import json
def get_body_json(request):
json_str = request.body
json_str = json_str.decode() # python3.6 無需執行此步
req_data = json.loads(json_str)
print(req_data['a'])
print(req_data['b'])
return HttpResponse('OK')
注意:使用postman必須註釋csrf功能,另外postman測試的時候網址後面一定要加斜槓!!!
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',
]
4.通過請求頭傳遞參數
/header_data/
request.META:python 字典,保存請求頭中的所有數據
請求中的任何HTTP頭部轉換爲HTTP_的鍵時,都會將所有字母大寫並將連接符替換爲下劃線,最後加上META前綴
request.META.get('HTTP_NAME')
# /header_data/
def get_header(request):
# 獲取請求頭傳遞的參數
type = request.META.get('CONTENT_TYPE')
name = request.META.get('HTTP_NAME')
return HttpResponse('OK')
Django和flask中request對象屬性對比
響應Response
響應對象的構造與說明
視圖訪問響應時返回HttpResponse類的對象或者子類的對象
response = HttpResponse(content='響應內容', content_type='響應體數據類型', status='狀態碼')
response['NAME'] = 'ITCAST' #響應頭可以直接將HttpResponse對象當做字典進行響應頭鍵值對的設置
return response
# 示例
# /get_response/
def get_response(request):
# 響應對象構造
response = HttpResponse('content body', content_type='text/html', status=200)
# 向響應頭中添加數據
response['NAME'] = 'ITCAST'
return response
返回頁面重定向(重點)
# 反向解析獲取index視圖所對應的url地址
req_url = reverse('users:index')
return redirect(req_url)
返回json數據(重點)
from django.http import JsonResponse
return JsonResponse({'name':monkey,'age',23})
狀態保持
cookie的設置和獲取
diango中cookie的設置和獲取:
response = HttpResponse('ok')
response.set_cookie(cookie名, value=cookie值, max_age=cookie有效期) # 3600(一小時過期)
return response
讀取:
def demo_view(request):
name = request.COOKIES.get('name')
print(name)
return HttpResponse('OK')
刪除:
def del_cookie(request):
response = HttpResponse('OK')
response.delete_cookie('name')
return response
session儲存說明
session:數據存儲在服務器,以key-value進行存儲。
特點: session依賴於cookie,每個客戶端的session數據的標識存儲到cookie中
flask session過期時間默認一個月,django session過期時間默認爲2周。
session的三種儲存方式
1.數據庫
存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'
2.混合本地緩存
存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
3.混合存儲
優先從本機內存中存取,如果沒有則從數據庫中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
session存儲到redis設置
安裝擴展 pip install django-redis
- 先將服務器緩存改爲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"
- 再將session設置到緩存中
session的設置和獲取
# /set_session/
def set_session(request):
# 設置session
request.session['name'] = 'itcast'
request.session['age'] = 12
return HttpResponse('OK')
# /get_session/
def get_session(request):
# 獲取session
name = request.session.get('name')
age = request.session.get('age')
return HttpResponse('name: %s age: %s' % (name, age))
session的操作
1) 以鍵值對的格式寫session。
request.session['鍵']=值
2)根據鍵讀取值。
request.session.get('鍵',默認值)
3)清除所有session,在存儲中刪除值部分。
request.session.clear()
4)清除session數據,在存儲中刪除session的整條數據。
request.session.flush()
5)刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值。
del request.session['鍵']
6)設置session的有效期
request.session.set_expiry(value)
類視圖
類視圖的基本使用
類視圖好處:
1.代碼更加清晰 2.代碼可重用性更高
class RegisterView(View):
def get(self,request):
# 返回註冊頁面
return HttpResponse('返回註冊頁面')
def post(self,request):
# 進行註冊處理
return HttpResponse('進行註冊處理')
def put(self,request):
# 使用哪個方法請求就def定義哪個請求方式
return HttpResponse('put方法被調用')
# 子應用配置urls.py
urlpatterns = [
url(r'^register/$', views.RegisterView.as_view(), name='register')
]
# 項目總的urls設置包含
類視圖原理
給類視圖函數添加裝飾器
注意:函數視圖的裝飾器不能直接加在類視圖方法上面,會報錯!
1)方法一:在urls中配置中裝飾
2)方法二:使用@method_decorator來進行裝飾器添加
def my_decorator(func):
def wrapper(request, *args, **kwargs):
print('自定義裝飾器被調用了')
print('請求路徑%s' % request.path)
return func(request, *args, **kwargs)
return wrapper
# 爲全部請求方法添加裝飾器
@method_decorator(my_decorator, name='dispatch')
class DemoView(View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
# 爲特定請求方法添加裝飾器
@method_decorator(my_decorator, name='get')
class DemoView(View):
def get(self, request):
print('get方法')
return HttpResponse('ok')
def post(self, request):
print('post方法')
return HttpResponse('ok')
Mixin擴展類
把一些通用的功能封裝到不同的父類中,子類需要哪些功能,就可以繼承哪些父類,這些父類就是Mixin擴展類。
DRF框架
中間件
Django中的中間件,就類似於flask中的鉤子函數:可以讓我們在請求之前或之後做一些處理。
基本使用
1)在子應用目錄下創建middleware.py(但是作用域時全局的),將以下模板代碼複製到裏面
def simple_middleware(get_response):
# 此處編寫的代碼僅在Django第一次配置和初始化的時候執行一次。
def middleware(request):
# 此處編寫的代碼會在每個請求處理視圖前被調用。
response = get_response(request)
# 此處編寫的代碼會在每個請求處理視圖之後被調用。
return response
return middleware
2)在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',
'users.middleware.my_middleware', # 添加中間件
]
多箇中間件執行順序
init部分的代碼調用和中間件的註冊順序是相反的
before request部分的代碼和中間件的註冊順序是相同的
after request部分的代碼和中間件的註冊順序是相反的
中間件的應用場景
可以在請求之前設置CSRF跨站請求僞造判斷保護
可以在請求之前設置黑名單校驗
模板
模板的基本使用
1.創建並設置模板文件的目錄
2.在視圖中使用render(request,‘模板文件’,‘字典’)調用模板
class TemplateView(View):
def get(self,request):
return render(request,'temp.html',context={'content':'hello'})
3.在urls中註冊地址
使用模板文件的詳細步驟
1.加載模板文件:指定所使用的模板文件,獲取模板對象
from django.template inport loader
temp = loader.get_template('模板文件')
2.進行模板渲染:給模板文件傳遞數據,將模板文件中的變量進行替換,獲取替換之後的內容
res_html = temp.render('傳遞給模板文件的字典數據')
3.創建響應對象
return HttpResponse(res_html)
Django模板和jinja2模板使用對比
1){{模板變量}}
Django使用模板變量時,無論是字典、列表或元組的元素,都需要使用".",不能使用[]
Django中的模板變量不能直接進行算術運算
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>
2)條件判斷
Django模板中在進行條件判斷時,比較操作符的兩邊必須有空格
3)循環/判斷
for循環:
{% for item in 列表 %}
循環邏輯
{{forloop.counter}}表示當前是第幾次循環,從1開始
{%empty%} 列表爲空或不存在時執行此邏輯
{% endfor %}
if條件:
{% if ... %}
邏輯1
{% elif ... %}
邏輯2
{% else %}
邏輯3
{% endif %}
比較運算符如下:
==
!=
<
>
<=
>=
布爾運算符如下:
and
or
not
注意:運算符左右兩側不能緊挨變量或常量,必須有空格。
{% if a == 1 %} # 正確
{% if a==1 %} # 錯誤
4)模板過濾器
{{模板變量|過濾器:參數}}
注:Django中的過濾器冒號後面的參數只能有一個
safe,禁用轉義,告訴模板這個變量是安全的,可以解釋執行
length,長度,返回字符串包含字符的個數,或列表、元組、字典的元素個數。
default,默認值,如果變量不存在時則返回默認值。
data|default:'默認值'
date,日期,用於對日期類型的值進行字符串格式化,常用的格式化字符如下:
Y表示年,格式爲4位,y表示兩位的年。
m表示月,格式爲01,02,12等。
d表示日, 格式爲01,02等。
j表示日,格式爲1,2等。
H表示時,24進制,h表示12進制的時。
i表示分,爲0-59。
s表示秒,爲0-59。
value|date:"Y年m月j日 H時i分s秒"
4)註釋
1)單行註釋語法如下:
{#...#}
2)多行註釋使用comment標籤,語法如下:
{% comment %}
...
{% endcomment %}
5)模板繼承
定義代碼塊:
{% block 名稱 %}
預留區域,可以編寫默認內容,也可以沒有默認內容
{% endblock 名稱 %}
子模版繼承:
{% extends "父模板路徑"%}
{% block 名稱 %}
實際填充內容
{{ block.super }}用於獲取父模板中block的內容
{% endblock 名稱 %}
數據庫
ORM框架
Django自帶ORM框架:通過類和對象可以直接進行數據庫操作,根據模型類自動生成表
數據庫鏈接配置
-
使用MySQL數據庫首先需要安裝驅動程序
pip install PyMySQL
-
在Django的工程同名子目錄的__init__.py文件中添加如下語句
from pymysql import install_as_MySQLdb install_as_MySQLdb()
作用是讓Django的ORM能以mysqldb的方式來調用PyMySQL。
-
修改DATABASES配置信息
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 數據庫主機 'PORT': 3306, # 數據庫端口 'USER': 'root', # 數據庫用戶名 'PASSWORD': 'mysql', # 數據庫用戶密碼 'NAME': 'django_demo' # 數據庫名字 } }
-
在MySQL中創建數據庫
create database django_demo default charset=utf8;
模型類定義
定義模型類,在models.py文件中定義
class BookInfo(models.Model):
"""圖書類模型"""
# 字段屬性 = models.字段類型(選項參數)
btitle = models.CharField(max_length=20,verbose_name="標題")
class Meta:
# 指定表名
db_table = "tb_books"
1) 數據庫表名
模型類如果未指明表名,Django默認以 小寫app應用名_小寫模型類名 爲數據庫表名。
可通過db_table 指明數據庫表名。
2) 關於主鍵
django會爲表創建自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設置某屬性爲主鍵列後django不會再創建自動增長的主鍵列。
默認創建的主鍵列屬性爲id,可以使用pk代替,pk全拼爲primary key。
3) 屬性命名限制
-
不能是python的保留關鍵字。
-
不允許使用連續的下劃線,這是由django的查詢方式決定的。
-
定義屬性時需要指定字段類型,通過字段類型的參數指定選項,語法如下:
屬性=models.字段類型(選項)
4)字段類型
類型 | 說明 |
---|---|
AutoField | 自動增長的IntegerField,通常不用指定,不指定時Django會自動創建屬性名爲id的自動增長屬性 |
BooleanField | 布爾字段,值爲True或False |
NullBooleanField | 支持Null、True、False三種值 |
CharField | 字符串,參數max_length表示最大字符個數 |
TextField | 大文本字段,一般超過4000個字符時使用 |
IntegerField | 整數 |
DecimalField | 十進制浮點數, 參數max_digits表示總位數, 參數decimal_places表示小數位數 |
FloatField | 浮點數 |
DateField | 日期, 參數auto_now表示每次保存對象時,自動設置該字段爲當前時間,用於"最後一次修改"的時間戳,它總是使用當前日期,默認爲False; 參數auto_now_add表示當對象第一次被創建時自動設置當前時間,用於創建的時間戳,它總是使用當前日期,默認爲False; 參數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤 |
TimeField | 時間,參數同DateField |
DateTimeField | 日期時間,參數同DateField |
FileField | 上傳文件字段 |
ImageField | 繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片 |
5) 選項
選項 | 說明 |
---|---|
null | 如果爲True,表示允許爲空,默認值是False |
db_column | 字段的名稱,如果未指定,則使用屬性的名稱 |
db_index | 若值爲True, 則在表中會爲此字段創建索引,默認值是False |
default | 默認 |
primary_key | 若爲True,則該字段會成爲模型的主鍵字段,默認值是False,一般作爲AutoField的選項使用 |
unique | 如果爲True, 這個字段在表中必須有唯一值,默認值是False |
6) 外鍵
在設置外鍵時,需要通過on_delete選項指明主表刪除數據時,對於外鍵引用表數據如何處理,在django.db.models中包含了可選常量:
- CASCADE 級聯,刪除主表數據時連通一起刪除外鍵表中數據
- PROTECT 保護,通過拋出ProtectedError異常,來阻止刪除主表中被外鍵應用的數據
- SET_NULL 設置爲NULL,僅在該字段null=True允許爲null時可用
生成遷移文件
python manage.py makemigrations
同步到數據庫中
python manage.py migrate
終端模式
Django shell 終端環境使用:
python manage.py shell
mysql數據庫的日誌文件:
記錄mysql數據庫操作
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
數據庫基本操作-新增數據
# 1.創建模型對象→對象.save()
book = BookInfo(
btitle="西遊記",
bpub_date="1998-1-1",
bread=10)
book.save()
# 2.模型類.objects.create(...)
hero = HeroInfo.objects.create(
hname="沙僧",
hcomment="你挑着擔",
hbook=book)
數據庫基本操作-更新/刪除
更新的2種方式:
>>> hero = HeroInfo.objects.get(id=2)
>>> hero.hname = '豬悟能'
>>> hero.save()
HeroInfo.objects.filter(過濾條件).update(更新數據)
>>> res = HeroInfo.objects.filter(id=3).update(hname='沙悟淨')
刪除的2種方式:
>>> hero = HeroInfo.objects.get(id=3)
>>> hero.delete()
HeroInfo.objects.filter(過濾條件).delete()
>>> HeroInfo.objects.filter(id=2).delete()
數據庫基本操作-查詢
models.py設置以下代碼,定義每個數據對象的顯示信息:
def __str__(self):
"""定義每個數據對象的顯示信息"""
return self.btitle
使用tests.py測試查詢,需要以下設置:
import os
if not os.environ.get('DJANGO_SETTINGS_MODULE'):
os.environ.setdefault("DJANGO_SETTINGS_MODULE","demo.settings")
import django
django.setup()
# 導入模型
from booktest.models import BookInfo,HeroInfo
if __name__ == "__main__":
print(BookInfo)
基本查詢-all&get&count
# 模型類.objects.
# get(查詢條件):返回一個模型對象,如果查不到,會報錯
book = BookInfo.objects.get(id=1)
# all():無參數,返回查詢到的所有數據
books = BookInfo.objects.all() # QuerySet查詢集:可以跟list一樣操作
# count():無參數,返回查詢到的結果數量
count = BookInfo.objects.count()
條件查詢-get&filter&exclude
# get(查詢條件):返回一個模型對象,如果查不到會報錯
book = BookInfo.objects.get(id__exact=1)
# filter(查詢條件):返回根據條件查詢到的結果,返回的是QuerySet
books = BookInfo.objects.filter(btitle__contains="傳") # 包含
books = BookInfo.objects.filter(btitle__startswith="天") # 以天開頭
books = BookInfo.objects.filter(btitle__endswith='部') # 以部結尾
books = BookInfo.objects.filter(btitle__isnull=False) # 標題不爲空
books = BookInfo.objects.filter(id__in=(1,3,5)) # 查詢id爲1,3,5的圖書
# gt 大於,gte 大於等於,lt 小於,lte 小於等於
books = BookInfo.objects.filter(id__gt=3) # 查詢id 大於3的圖書
# exclude(查詢條件):查詢不滿足條件的結果數據,返回的是QuerySet
books = BookInfo.objects.exclude(id=3) # 查詢id不等於3的圖書
# 日期查詢
# year、month、day、week_day、hour、minute、second:對日期時間類型的屬性進行運算
books = BookInfo.objects.filter(bpub_date__year=1980) # 查詢1980年發表的圖書
books = BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1)) # 該日期以後發表的圖書
數據查詢-F對象&Q對象
# F對象:用於查詢字段之間的比較
from django.db.models import F
books = BookInfo.objects.filter(bread__gte=F("bcomment")) # 查詢閱讀量大於等於評論量的圖書
books = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)# 閱讀量大於2倍評論量的圖書
# Q對象:用戶查詢時條件之間的邏輯關係 與或非
# &表示邏輯與,|表示邏輯或 ,~表示非
from django.db.models import Q
BookInfo.objects.filter(Q(bread__gt=20)&Q(id__lt=3)) # 查詢閱讀量大於20,並且編號小於3的圖書
BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3)) # 查詢閱讀量大於20,或編號小於3的圖書
BookInfo.objects.filter(~Q(pk=3)) # 查詢編號不等於3的圖書
數據查詢-聚合操作&排序
# Avg 平均,Count 數量,Max 最大,Min 最小,Sum 求和
from django.db.models import Sum,Avg,Max,Min,Count
count = BookInfo.objects.aggregate(Sum('bread')) # 返回dict: {'bread__sum': 136}
res = BookInfo.objects.aggregate(Count('id')) # 查詢數量
# 排序 返回查詢集QuerySet
books = BookInfo.objects.order_by('bread') # 按照閱讀量從小到大進行排序
books = BookInfo.objects.order_by('-bread') # 按照閱讀量從大到小進行排序
關聯查詢(查詢和對象關聯的數據)
# 1.查詢和西遊記關聯的英雄人物信息
book = BookInfo.object.get(btitle='西遊記')
heros = book.heroinfo_set.all()
# 2.查詢id爲1的圖書關聯的英雄人物信息
book = BookInfo.objects.get(id = 1)
heros = book.heroinfo_set.all()
# 3.查詢id爲1的英雄人物關聯的圖書信息
hero = HeroInfo.objects.get(id = 1)
book = hero.hbook
# 4.查詢和孫悟空關聯的圖書信息
hero = HeroInfo.objects.get(hname ='孫悟空')
book = hero.hbook
查詢和對象關聯的數據:
BookInfo(一類)
HeroInfo(多類)
一對多:HeroInfo類中有一個外鍵關聯屬性:hbook = models.ForeignKey(BookInfo)
查詢和圖書對象關聯的英雄數據(由一查多):
例子:heros = book.heroinfo_set.all()
一類對象.多類名小寫_set.all()
查詢和英雄關聯的圖書數據(由多查一):
例子:book=hero.hbook
多類對象.關聯屬性
查詢集QuerySet
以下函數返回的都是查詢集:
all():返回所有數據。
filter():返回滿足條件的數據。
exclude():返回滿足條件之外的數據。
order_by():對結果進行排序。
查詢集可以像list一樣進行操作:遍歷。取下標,切片(查詢集切片時下標不能爲負),QuerySet對象可以繼承調用上面任何查詢相關方法。
BookInfo.objects.filter(id__gt=3).order_by('bread')
QuerySet對象還有一個方法叫:exists→判斷查詢集中是否有數據,有返回True,沒有返回Flase
兩大特點:
惰性查詢:只有在使用查詢集中的數據時纔會真正發生數據庫的查詢
數據緩存:使用同一個查詢集中的數據,只有第一次使用的時候會查詢數據庫,然後會將查詢的結果保存起來,
再使用這個查詢集時,使用的時保存起來的數據,不會再去查數據庫。
Admin管理
Admin站點管理的基本使用
Django自帶admin站點管理功能。
1.語言和時區的本地化
2.創建管理員用戶
python manage.py createsuperuser
3.APP應用配置
4.註冊模型類
在子應用admin.py文件中註冊模型類
admin.site.register(模型類)
列表頁和編輯頁相關屬性
自定義Admin站點管理頁面
1.定義模型Admin管理類 admin.py
class BookInfoAdmin(admin.ModelAdmin):
# Django提供了很多類屬性,通過對應的屬性就可以控制管理界面對應內容的展示
# 顯示哪些字段或方法
list_display = ["id" , "btitle","pub_date"]
# 每頁顯示多少條
list_per_page=100
# 編輯頁顯示字段
fields = ['btitle', 'bpub_date']
# 分組顯示編輯頁字段(與編輯頁顯示字段衝突,只能寫一種)
fieldsets = (
('基本', {'fields': ['btitle', 'bpub_date']}),
('高級', {
'fields': ['bread', 'bcomment'],
'classes': ('collapse',) # 是否摺疊顯示
}))
class HeroInfoAdmin(admin.ModelAdmin):
...
# 右側欄過濾器
list_filter = ['hbook', 'hgender']
# 搜索框
search_fields = ['hname']
2.註冊模型類時將模型類和Admin管理類對應起來
admin.site.register(BookInfo,BookInfoAdmin)
admin.site.register(HeroInfo,HeroInfoAdmin)
使用pub_date方法的相關models.py配置:
class BookInfo(models.Model):
...
def pub_date(self):
return self.bpub_date.strftime('%Y年%m月%d日')
# 設置方法那一列的字段描述
pub_date.short_description = '出版日期'
# 讓方法對應的那一列支持排序
pub_date.admin_order_field = 'bpub_date'
關聯對象
Admin站點標題設置
在admin.py文件中添加一下信息
from django.contrib import admin
admin.site.site_header = 'Monkey-文字LOGO'
admin.site.site_title = '前瞻網絡-網站標題'
admin.site.index_title = '來了老弟!-首頁標語'
Admin站點上傳圖片
打開models.py設置字段
image = models.ImageField(upload_to='booktest',verbose_name='圖片', null=True)
- upload_to 選項指明該字段的圖片保存在MEDIA_ROOT目錄中的哪個子目錄
然後進行數據庫遷移
python manage.py makemigrations
python manage.py migrate
使用Admin站點保存圖片,需要安裝Python的圖片操作包
pip install Pillow==4.1.0
指定Admin站點上傳圖片保存的目錄
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")