WSGI服務網關接口:Web Server Gateway Interface縮寫。html
WSGI是python定義的Web服務器和Web應用程序之間或框架之間的通用接口標準。前端
WSGI定義:Web開發者實現了一個函數,並響應HTTP請求。python
WSGI將Web組件分紅三類:Web服務器(WSGI Server),Web中間件(WSGI Middleware),Web用用程序(WSGI Application).正則表達式
Web服務器接收HTTP請求,調用WSGI接口標準註冊的WSGI Application,最後將響應返回給客戶端。數據庫
Web應用的本質:1.瀏覽器發送HTTP請求。django
2.服務器接收請求,生成HTML頁面。瀏覽器
3.服務器將HTML頁面當成HTTP響應的body發送給瀏覽器。安全
4.瀏覽器接收到HTTP響應,並從HTTP Body中HTML並渲染出來服務器
django的中間件(Middleware),其實就是一個類,在請求前和請求後,django會根據本身的規則並在合適的時機執行中間件中相應的方法。app
中間件的官方說法是中間件是一個用來處理django的請求和相應的框架級別的鉤子。在全局範圍內改變django的輸入和輸出,每一箇中間件都有特定的功能。
中間件能夠定義五個方法:1.process_request(self, request)
2.process_response(self, request, response)
3.process_view(self, request, view_func, view_args, view_kwargs)
4.process_exception(self, request, exception)
5.process_template_response(self, request, response)
以上方法返回的能夠是None也能夠是HttpResponse對象,若是是None,這繼續按照django的規則繼續執行下面的中間件,若是是HttpResponse對象,則直接把對象返回給用戶。
process_request有一個參數,就是request,這個request和視圖函數中的request是同樣的。它的返回值能夠是None也能夠是HttpResponse對象。返回值是None的話,按正常流程繼續走,交給下一個中間件處理,若是是HttpResponse對象,Django將不執行視圖函數,而是直接走本中間件的process_response方法,倒序返回,將相應對象返回給瀏覽器。
process_response有兩個參數,一個是request,一個是response。這裏面的request和process_request裏面的參數request是同樣的對象,response是視圖函數返給回給用戶的是Httpresponse對象,而且該方法返回值必須是HttpResponse對象。
process_view有四個參數:1.request是HttpResponse對象
2.view_func是django即將用到的視圖函數,它是實際的視圖函數
3.view_args是傳遞給視圖函數的位置參數的列表
4.view_kwargs是傳遞給視圖函數的關鍵之參數的字典
5.args和kwargs都不包含第一個參數request
process_view它應該返回一個None或HttpResponse對象,若是返回None,則繼續執行剩下的中間件的process_view方法,而後再執行相應的視圖。若是返回HttpResponse對象,則再也不執行剩下的process_view和後面的視圖函數,它將執行中間件的process_response方法並將應用到HttpResponse並返回結果。
process_exception有兩個參數:request是一個HttpResponse對象,exception是視圖產生的Exception對象。這個方法是隻有視圖函數執行異常時才執行的,它返回的對象能夠是一個None也能夠是一個HttpResponse對象。若是是HttpResponse對象,django將調用模板和process_response方法並返回給瀏覽器。,不然默認處理異常。
它有兩個參數,request參數是HttpResponse對象,response參數是TemplateResponse對象(由視圖函數或中間件產生)。
URL配置(URLconf)就像django所支撐網站的目錄,它的本質就是該URL和要爲該URL調用的視圖函數之間的映射表。
# 基本配置
from djago.conf.urls import url
urlpattrens = [
url(正則表達式,views視圖函數名,參數,別名),
]
# 注意事項
1.從上到下一次匹配,一旦匹配成功就再也不匹配
2.不須要添加一個前導的斜槓,由於每一個URL都有
3.每一個正則表達式前的r是可選的,但建議加上
# 補充說明
APPEEND_SLASH = True # django默認爲True,做用就是自動在網址末尾加/
# 起別名 url(r'^home', views.home, name='home'), # 給個人url匹配模式起名爲 home url(r'^index/(\d*)', views.index, name='index'), # 給個人url匹配模式起名爲index
這樣:
在模板裏面能夠這樣引用:
{% url 'home' %}
在views函數中能夠這樣引用:
from django.urls import reverse reverse("index", args=("2018", ))
即便不一樣的APP使用相同的URL名稱,URL的命名空間模式也可讓你惟一反轉命名的URL。
舉個例子:
project中的urls.py
from django.conf.urls import url, include urlpatterns = [ url(r'^app01/', include('app01.urls', namespace='app01')), url(r'^app02/', include('app02.urls', namespace='app02')), ]
app01中的urls.py
from django.conf.urls import url from app01 import views app_name = 'app01' urlpatterns = [ url(r'^(?P<pk>\d+)/$', views.detail, name='detail') ]
app02中的urls.py
from django.conf.urls import url from app02 import views app_name = 'app02' urlpatterns = [ url(r'^(?P<pk>\d+)/$', views.detail, name='detail') ]
如今,個人兩個app中 url名稱重複了,我反轉URL的時候就能夠經過命名空間的名稱獲得我當前的URL。
語法:
'命名空間名稱:URL名稱'
模板中使用:
{% url 'app01:detail' pk=12 pp=99 %}
views中的函數中使用
v = reverse('app01:detail', kwargs={'pk':11})
這樣即便app中URL的命名相同,我也能夠反轉獲得正確的URL了。
# 這種形式是無名分組
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
沒有命名的正則表達式組(經過圓括號)來捕獲URL中的值並以位置參數傳遞給視圖。在更高級的用法中,可使用命名的正則表達式組來捕獲URL 中的值並以關鍵字 參數傳遞給視圖。
在Python 正則表達式中,命名正則表達式組的語法是(?P<name>pattern)
,其中name
是組的名稱,pattern
是要匹配的模式。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail), ]
這個實現與無名分組徹底相同,只有一個細微的差異:捕獲的值做爲關鍵字參數而不是位置參數傳遞給視圖函數。例如:
/articles/2005/03/ 請求將調用views.month_archive(request, year='2005', month='03')函數 /articles/2003/03/03/ 請求將調用函數views.article_detail(request, year='2003', month='03', day='03')。
python的模板:HTML代碼+邏輯控制代碼
# 變量 用雙大括號來引用變量 用法:{{ title }}
# 邏輯 用大括號和百分號組合 用法:{% for user in user_list %} {% endfor %}
# 點 . 在模板裏面有特殊的含義,就是獲取對象的相應屬性值 {{ user.name }}
# 模板中支持的寫法
{# 取l中的第一個參數 #} {{ l.0 }} {# 取字典中key的值 #} {{ d.name }} {# 取對象的name屬性 #} {{ person_list.0.name }} {# .操做只能調用不帶參數的方法 #} {{ person_list.0.dream }}
語法: {{ value|filter_name:參數 }}
{{ value|default:"nothing" }}
{{ value|length }} # 返回value的長度
{{ value|filesizeformat }} # 將十進制數轉爲爲KB,MB,GB等
{{ value|slice:"2:-1" }} # 切片
{{ value|data:"Y-m-d H:i:s" }} # 格式化時間
{{ value|safa }} # 告訴django這段代碼是安全的,沒必要轉譯
{{ value|truncatechars:9 }} # 截斷,若是value的字符數大於9,則只顯示前9個字符,後面的用...表示。
{{ value|upper }} # 將value的字母全變成大寫
{{ value|add:2 }} # value值+2並顯示
{{ value|cut:"a" }} # 移除指定字符
from django import template
register = template.Library()
@register.filter(name="cut")
def cut(value, args):
return value.replace(args, "")
@register.filter(name="add")
def add(value):
return "{}很可愛!".format(value)
{# 先導入咱們自定義filter那個文件 #} {% load app01_filters %} {# 使用咱們自定義的filter #} {{ somevariable|cut:"0" }} {{ value|add }}
注意:以上代碼要在django項目中使用
前端未完待續......
django的兩種處理請求的方式:FBV和CBV
# urls.py中 url(r'^add_class/$', views.AddClass.as_view()),
HttpResponse類位於django.http模塊中。
傳遞字符串
from django.http import HttpResponse response = HttpResponse("Here's the text of the Web page.") response = HttpResponse("Text only, please.", content_type="text/plain")
設置或刪除響應頭信息
response = HttpResponse() response['Content-Type'] = 'text/html; charset=UTF-8' del response['Content-Type']
HttpResponse.content:響應內容
HttpResponse.charset:響應內容的編碼
HttpResponse.status_code:響應的狀態碼
JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。
from django.http import JsonResponse response = JsonResponse({'foo': 'bar'}) print(response.content) b'{"foo": "bar"}'
默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數。
response = JsonResponse([1, 2, 3], safe=False)
結合一個給定的模板和一個給定的上下文字典,並返回一個渲染後的 HttpResponse 對象。
from django.shortcuts import render def my_view(request): # 視圖的代碼寫在這裏 return render(request, 'myapp/index.html', {'foo': 'bar'})
參數能夠是:
默認返回一個臨時的重定向;傳遞permanent=True 能夠返回一個永久的重定向。
你能夠用多種方式使用redirect() 函數。
傳遞一個具體的ORM對象(瞭解便可)
將調用具體ORM對象的get_absolute_url() 方法來獲取重定向的URL:
from django.shortcuts import redirect def my_view(request): ... object = MyModel.objects.get(...) return redirect(object)
傳遞一個視圖的名稱
def my_view(request): ... return redirect('some-view-name', foo='bar')
傳遞要重定向到的一個具體的網址
def my_view(request): ... return redirect('/some/url/')
固然也能夠是一個完整的網址
def my_view(request): ... return redirect('http://example.com/')
默認狀況下,redirect() 返回一個臨時重定向。以上全部的形式都接收一個permanent 參數;若是設置爲True,將返回一個永久的重定向:
def my_view(request): ... object = MyModel.objects.get(...) return redirect(object, permanent=True)
擴展閱讀:
臨時重定向(響應狀態碼:302)和永久重定向(響應狀態碼:301)對普通用戶來講是沒什麼區別的,它主要面向的是搜索引擎的機器人。
A頁面臨時重定向到B頁面,那搜索引擎收錄的就是A頁面。
A頁面永久重定向到B頁面,那搜索引擎收錄的就是B頁面。
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增長一條數據,能夠接受字典類型數據 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 獲取單條數據,不存在則報錯(不建議) # models.Tb1.objects.all() # 獲取所有 # models.Tb1.objects.filter(name='seven') # 獲取指定條件的數據 # 刪 # # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 將指定條件的數據更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save() # 修改單條數據 # save是更改全部字段,即便更改一個字段,也會將全部字段從新賦值, 不推薦 # update更改,只更改修改的字段,推薦使用 # update方式修改不能用get的緣由是:update是QuerySet對象的方法,get返回的是一個model對象,它沒有update方法,而filter返回的是一個QuerySet對象(filter裏面的條件可能有多個條件符合,好比name='alvin',可能有兩個name='alvin'的行數據) 基本操做
# 查詢相關API: # <1>filter(**kwargs): 它包含了與所給篩選條件相匹配的對象 # <2>all(): 查詢全部結果 # <3>get(**kwargs): 返回與所給篩選條件相匹配的對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。 #-----------下面的方法都是對查詢的結果再進行處理:好比 objects.filter.values()-------- # <4>values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列 model的實例化對象,而是一個可迭代的字典序列 # <5>exclude(**kwargs): 它包含了與所給篩選條件不匹配的對象 # <6>order_by(*field): 對查詢結果排序 # <7>reverse(): 對查詢結果反向排序 # <8>distinct(): 從返回結果中剔除重複紀錄 # <9>values_list(*field): 它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列 # <10>count(): 返回數據庫中匹配查詢(QuerySet)的對象數量。 # <11>first(): 返回第一條記錄 # <12>last(): 返回最後一條記錄 # <13>exists(): 若是QuerySet包含數據,就返回True,不然返回False 查詢相關API
# 獲取個數 # # models.Tb1.objects.filter(name='seven').count() # 大於,小於 # # models.Tb1.objects.filter(id__gt=1) # 獲取id大於1的值 # models.Tb1.objects.filter(id__gte=1) # 獲取id大於等於1的值 # models.Tb1.objects.filter(id__lt=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lte=10) # 獲取id小於10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、2二、33的數據 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # isnull # Entry.objects.filter(pub_date__isnull=True) # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 範圍bettwen and # 其餘相似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # group by # # from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" # limit 、offset # # models.Tb1.objects.all()[10:20] # regex正則匹配,iregex 不區分大小寫 # # Entry.objects.get(title__regex=r'^(An?|The) +') # Entry.objects.get(title__iregex=r'^(an?|the) +') # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) # hour # # Event.objects.filter(timestamp__hour=23) # Event.objects.filter(time__hour=5) # Event.objects.filter(timestamp__hour__gte=12) # minute # # Event.objects.filter(timestamp__minute=29) # Event.objects.filter(time__minute=46) # Event.objects.filter(timestamp__minute__gte=29) # second # # Event.objects.filter(timestamp__second=31) # Event.objects.filter(time__second=2) # Event.objects.filter(timestamp__second__gte=31) 進階操做
利用雙下劃線和 _set 將表之間的操做鏈接起來
class UserProfile(models.Model): user_info = models.OneToOneField('UserInfo') username = models.CharField(max_length=64) password = models.CharField(max_length=64) def __unicode__(self): return self.username class UserInfo(models.Model): user_type_choice = ( (0, u'普通用戶'), (1, u'高級用戶'), ) user_type = models.IntegerField(choices=user_type_choice) name = models.CharField(max_length=32) email = models.CharField(max_length=32) address = models.CharField(max_length=128) def __unicode__(self): return self.name class UserGroup(models.Model): caption = models.CharField(max_length=64) user_info = models.ManyToManyField('UserInfo') def __unicode__(self): return self.caption class Host(models.Model): hostname = models.CharField(max_length=64) ip = models.GenericIPAddressField() user_group = models.ForeignKey('UserGroup') def __unicode__(self): return self.hostname 表結構實例
user_info_obj = models.UserInfo.objects.filter(id=1).first() print(user_info_obj.user_type) print(user_info_obj.get_user_type_display()) print(user_info_obj.userprofile.password) user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first() print(user_info_obj.keys()) print(user_info_obj.values())