一、django、tornado、flask比較html
Django: 1個重武器,包含了web開發中經常使用的功能、組件的框架;(ORM、Session、Form、Admin、分頁、中間件、信號、緩存、ContenType....);python
Tornado: 最大特性就是異步非阻塞、原生支持WebSocket協議;jquery
Flask:封裝功能不及Django完善,性能不及Tornado,可是Flask的第三方開源組件比豐富;web
使用參考ajax
1. 小型web應用設計的功能點很少使用Flask;
2. 大型web應用設計的功能點比較多使用的組件也會比較多,使用Django(自帶功能多不用去找插件);
3. 若是追求性能能夠考慮Tornado;sql
二、MVC和MVT比較數據庫
MVC Model(數據庫 ) View(模板文件) Controller(業務處理)django
M( Model): 主要封裝對數據庫層的訪問,對數據庫中的數據進行增、刪、改、查操做。
V( View): 用於封裝結果,生成頁面展現的html內容。
C(Controller): 用於接收請求,處理業務邏輯,與Model和View交互,返回結果。json
MTV Model(數據庫) Template(模板文件) View( 業務處理)flask
M( Model): 與MVC中的M功能相同,負責和數據庫交互,進行數據處理。
V( View): 與MVC中的C功能相同,接收請求,進行業務處理,返回應答。
T(Template): 與MVC中的V功能相同,負責封裝構造要返回的html。
一、安裝django
pip3 install django==2.0.4
二、建立django項目
C:\Users\tom> d: # 進入d盤 D:\> django-admin startproject mysite # 建立django項目(能夠看到c盤生成了mysite文件夾的django項目) D:\> cd mysite # 進入項目目錄 D:\mysite> python manage.py runserver 127.0.0.1:8000 # 運行mysite項目 # 瀏覽器訪問:http://127.0.0.1:8000/
三、建立子應用
c:\mysite>python manage.py startapp app01
四、django項目和子應用各文件做用
C:. │ db.sqlite3 # sqlite數據庫文件(settings.py中默認鏈接的數據庫) │ manage.py # 項目管理腳本 │ ├─app01 (子應用目錄) │ │ admin.py # 配置django admin後臺 │ │ apps.py │ │ models.py # 配置django表,負責和數據庫交互,進行數據處理 │ │ tests.py │ │ views.py # 接收請求,進行業務處理,返回應答 │ │ __init__.py │ │ │ └─migrations │ __init__.py │ └─mysite │ settings.py # 項目配置文件 │ urls.py # 總路由 │ wsgi.py │ __init__.py
五、settings.py基本配置
1)配置模板的路徑(在項目根路徑下建立文件夾 D:\mysite\templates)
TEMPLATES = [ { 'DIRS': [os.path.join(BASE_DIR,'templates')], }, ]
TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'templates'),)
2)配置靜態目錄(在項目根路徑下建立文件夾 D:\mysite\static)
#像ccs和js這些靜態文件若是想要使用必須在這裏配置路徑 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), )
3)註釋CSRF(若是以post方式提交請求能夠先註釋這裏進行測試)
MIDDLEWARE = [ # 'django.middleware.csrf.CsrfViewMiddleware', ]
4) 修改settings.py中時區
#### 一、Django默認配置是: TIME_ZONE = 'UTC' LANGUAGE_CODE = 'en-us' #### 二、Django1.9之前應設置爲: TIME_ZONE = 'Asia/Shanghai' LANGUAGE_CODE = 'zh-cn' ####三、Django1.9之後至目前的2.1,應設置爲: LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'
一、render/redirect/HttpResponse 函數用法
render : 返回html頁面
redirect : 重定向到新的頁面
HttpResponse : 返回字符串(通常爲json字符串)
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
from django.shortcuts import render,redirect,HttpResponse import json def index(request): return render(request, 'index.html', {'users':['zhangsan','lisi','wangwu']}) # return redirect('https://www.baidu.com') # return HttpResponse(json.dumps({"name":"zhangsan"}))
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>我是首頁</h1> {{ users }} </body> </html>
二、模板使用
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
from django.shortcuts import render,redirect,HttpResponse def index(request): return render(request, 'index.html', { 'users':['zhangsan','lisi','wangwu'], 'data':{"name":"zhangsan","age":100,"sex":"人妖"}, 'num': 12, })
<body> <h1>一、users: 循環列表</h1> {% for u in users %} <p>{{ u }}</p> {% endfor %} <h1>二、data:循環字典</h1> {% for k,v in data.items %} <p>{{ k }} -- {{ v }}</p> {% endfor %} <h1>三、if判斷</h1> {% if num > 16 %} <a>num大於16</a> {% else %} <a>num小於16</a> {% endif %} </body>
一、無正則匹配url (http://127.0.0.1:8000/index/?nid=1&pid=2)
二、基於(\d+)正則的url
三、基於正則分組(?P<nid>\d+),能夠不考慮接收參數順序 (推薦)
四、使用name構建本身想要的url
五、Django路由分發 並使用name構建url路徑
re_path(r'app01/',include(('app01.urls','app01'),namespace='app01'))
from django.contrib import admin from django.urls import path, re_path,include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'index1/$', views.index1, name='indexname1'), # 方法1:無正則匹配url re_path('index2/(\d+)/$', views.index2, name='indexname2'), # 方法2:基於(\d+)正則的url re_path('index3/(?P<nid>\d+)/(?P<pid>\d+)/$', views.index3, name='indexname3'), # 方法3:基於(\d+)正則的url re_path('index4/$', views.index4), # 方法4:使用name構建本身想要的url path('app01/', include('app01.urls', namespace='app01')), # 方法5:Django路由分發 ]
from django.shortcuts import render,redirect,HttpResponse import json from django.urls import reverse # 方法1:無正則匹配url( http://127.0.0.1:8000/index1/?uid=1 ) def index1(request): print( request.GET ) # {"uid": "1"} nid = request.GET.get('uid') # 1 return HttpResponse('無正則匹配url') # 方法2:基於(\d+)正則的url( http://127.0.0.1:8000/index2/1/ ) def index2(request, uid): print( uid ) # 1 return HttpResponse('基於(\d+)正則的url') # 方法3:基於正則分組(?P<nid>\d+)( http://127.0.0.1:8000/index3/1/2/ ) def index3(request, nid, pid): print(nid) # 1 print(pid) # 2 return HttpResponse('基於正則分組url') # 方法4:使用name構建本身想要的url (http://127.0.0.1:8000/index4/) def index4(request): url1 = reverse('indexname1') # /index1/ url2 = reverse('indexname2', args=(1,)) # /index2/1/2/ url3 = reverse('indexname3', kwargs={'pid': 1, "nid":2}) # /index3/1/2/ return render(request, 'index.html') # 方法5:Django路由分發 (http://127.0.0.1:8000/app01/aaa/) def aaa(request): return HttpResponse('aaa')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <p><a href="{% url 'indexname1' %}"> 無正則匹配: http://127.0.0.1:8000/index/ </a></p> <p><a href="{% url 'indexname2' 1 %}"> 基於(\d+)正在匹配: http://127.0.0.1:8000/index2/1/ </a></p> <p><a href="{% url 'indexname3' 1 2 %}"> 基於正則分組url: http://127.0.0.1:8000/index3/1/2/ </a></p> </body> </html>
#! /usr/bin/env python # -*- coding: utf-8 -*- from django.urls import path,re_path app_name='app01' from app01 import views urlpatterns = [ re_path(r'aaa/$', views.aaa, name='aaa'), ]
一、FBV(function base view):在views.py文件中使用函數
def aaa(request): return HttpResponse('aaa')
二、CBV(class base view):在views.py文件中使用類
一、 dispatch是父類中用來反射的函數,找對應的函數(比對應函數先執行)
二、 好比你發送post請求就能夠經過dispatch找到對應的post函數進行處理,get就會找到get函數處理
#! /usr/bin/env python # -*- coding: utf-8 -*- from django.urls import path,re_path app_name='app01' from app01 import views urlpatterns = [ re_path(r'home/$', views.Home.as_view(), name='home'), ]
from django.views import View class Home(View): '''使用CBV時必需要繼承view父類''' def dispatch(self, request, *args, **kwargs): # 調用父類中的dispatch result = super(Home,self).dispatch(request, *args, **kwargs) # 使用result主動繼承view父類,而後return就能夠重寫父類的dispath方法 return result # 在這裏使用get發來請求就會調用get方法,使用post發來請求就會調用post方法 def get(self,request): print(request.method) return HttpResponse('get') def post(self,request): print(request.method,'POST') return HttpResponse('post')
一、獲取請求數據
# 一、request.POST # 二、request.GET # 三、request.FILES # 四、request.getlist # 五、request.method # 六、request.path_info #獲取當前url
二、舉例
from django.contrib import admin from django.urls import path, re_path from app01 import views urlpatterns = [ re_path(r'login/$', views.login, name='login'), ]
def login(request): if request.method == 'GET': return render(request, 'login.html') elif request.method == 'POST': post_data = request.POST # {"user": "naiqiang.xiao", "gender": "1", "favor": "33", "city": "bj"} mul_list = request.POST.getlist('favor') # ['11', '22', '33'] return render(request, 'login.html')
<form action="/login/" method="post" enctype="multipart/form-data"> <p> <span>input提交:</span> <input type="text" name="user" placeholder="用戶名"> </p> {# 一、單選框,返回單條數據的列表 #} <p> <span>性別: </span> 男:<input type="radio" name="gender" value="1"> 女:<input type="radio" name="gender" value="2"> </p> {# 二、多選框、返回多條數據列表 #} <p> <span>愛好: </span> 籃球:<input type="checkbox" name="favor" value="11"> 排球:<input type="checkbox" name="favor" value="22"> 足球:<input type="checkbox" name="favor" value="33"> </p> {# 三、多選,返回多條數據的列表 #} <p> <span>地址: </span> <select name="city"> <option value="bj">北京</option> <option value="sh">上海</option> <option value="gz">廣州</option> </select> </p> <input type="submit" value="提交"> </form>
三、form表單中三個參數做用
''' action="/login/" method="post" enctype="multipart/form-data" ''' # 一、action="/login/" # form表單數據提交的路徑 # 二、method="post" # 以什麼方式提交form表單 # 三、enctype="multipart/form-data" # 若是須要提交文件須要這個標註
一、使用from表單上傳圖片 及 預覽功能
1) enctype就是encodetype就是編碼類型的意思。
2) 默認狀況下,enctype的值是application/x-www-form-urlencoded,不能用於文件上傳。
3) multipart/form-data是指定將文件以二進制的形式上傳,這樣能夠實現多種類型的文件上傳。
from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'upload/',views.upload), ]
from django.shortcuts import render import os def upload(request): if request.method == 'GET': return render(request, 'upload.html') elif request.method == 'POST': obj = request.FILES.get('filename') # 獲取上傳圖片對象 file_path = os.path.join('static','images', obj.name) # static\images\aa.jpg f = open(file_path, mode='wb') for i in obj.chunks(): f.write(i) f.close() imgpath = os.path.join('images',obj.name) # images\aa.jpg return render(request, 'upload.html',{'imgpath': imgpath})
{% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <form action="/upload/" method="post" enctype="multipart/form-data"> {% csrf_token %} <p><input type="file" name="filename"></p> <input type="submit" value="提交"> </form> <p>圖片預覽</p> <p><img src="{% static imgpath %}"></p> </body> </html>
二、使用jquery ajax上傳圖片
1)JQuery AJAX說明
一、jQuery其實就是一個JavaScript的類庫,其將複雜的功能作了上層封裝,使得開發者能夠在其基礎上寫更少的代碼實現更多的功能
二、jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject
2) FormData對象
一、FormData對象用以將數據編譯成鍵值對,以便用XMLHttpRequest來發送數據。
二、 其主要用於發送表單數據,但亦可用於發送帶鍵數據(keyed data),而獨立於表單使用。
三、比起普通的ajax,使用FormData的最大優勢就是咱們能夠異步上傳一個二進制文件。
3)contentType:(默認: "application/x-www-form-urlencoded")
一、發送信息至服務器時內容編碼類型(false標識不要對提交的數據)。
二、若是你明確地傳遞了一個content-type給 $.ajax() 那麼他一定會發送給服務器(即便沒有數據要發送)
三、設置false做用:告訴JQuery不要設置內容格式
4)processData(默認: true)
一、默認狀況下,經過data選項傳遞進來的數據,都會處理轉化成一個查詢字符串
二、若是要發送 DOM 樹信息或其它不但願轉換的信息,請設置爲 false。
三、設置false做用:告訴JQuery不要特殊處理這個數據
from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'ajax/$',views.ajax_upload), ]
from django.shortcuts import render,HttpResponse import os import json def ajax_upload(request): if request.method == 'GET': return render(request, 'ajaxupload.html') elif request.method == 'POST': obj = request.FILES.get('fafafa') username = request.POST.get('username') # root file_path = os.path.join('static','images', obj.name) # static\images\aa.jpg with open(file_path,'wb') as f: for item in obj.chunks(): f.write(item) ret = {'code':True,'data':'sucess'} return HttpResponse(json.dumps(ret))
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <div> <input type="file" id="fafafa" name="afafaf"> <a class="upload">上傳</a> </div> <input type="button" value="提交jQuery" onclick="fqSubmit();"> <script src="/static/jquery-1.12.4.js"></script> <script> function fqSubmit(){ var file_obj = document.getElementById('fafafa').files[0]; var fd = new FormData(); // FormData對象能夠傳字符串,也能夠傳文件對象 fd.append('username','root'); fd.append('fafafa',file_obj); var xhr = new XMLHttpRequest(); $.ajax({ url:'/ajax/', type:'POST', data:fd, //jquery Ajax上傳文件必須指定processData,contentType參數 processData:false, //告訴JQuery不要特殊處理這個數據 contentType:false, //告訴JQuery不要設置內容格式 success:function(arg){ console.log(111,arg); //後臺返回的數據 {"code": true, "data": "sucess"} } }) } </script> </body> </html>
一、ajax登陸
from django.contrib import admin from django.urls import path, re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'login/', views.login, name='login'), ]
from django.shortcuts import render,HttpResponse import os import json def login(request): if request.method == 'GET': return render(request, 'login.html') elif request.method == 'POST': print(request.POST) username = request.POST.get('username') password = request.POST.get('password') print(username, password) if username == 'tom' and password == '123456': return HttpResponse(json.dumps({'status':True})) else: return HttpResponse(json.dumps({'status':False}))
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h2>登陸</h2> <div style=""> <p> <input name="username" id="username"> </p> <p> <input name="password" type="password" id="password"> </p> <p> <input type="button" value="提交" onclick="ajaxSubmit()"> </p> <p id="err-msg" style="color: red;"></p> </div> <script src="/static/jquery-1.12.4.js"></script> <script> function ajaxSubmit() { var username = document.getElementById('username').value; var password = document.getElementById('password').value; $.ajax({ url: '/login/', // 提交url data: {'username':username, 'password':password}, // 提交數據 type: 'POST', // 提交方式 dataType: 'JSON', // 將數據裝換成json格式提交 traditional: true, // tradtional爲true阻止深度序列化 success: function (data) { if(data.status == true){ alert('登陸成功') document.getElementById('err-msg').innerText = '' location.href='http://www.baidu.com' }else { console.log('在頁面顯示錯誤信息') document.getElementById('err-msg').innerText = '用戶名或密碼錯誤' } } }) } </script> </body> </html>
二、先後端交互必學知識點
1. Dom操做 : http://www.javashuo.com/article/p-xxhoxhih-cg.html
2. jquery使用整理 : http://www.javashuo.com/article/p-mandouxc-cq.html
3. ajax最全整理 : http://www.javashuo.com/article/p-nozltshg-cw.html
三、make_password & check_password
from django.contrib.auth.hashers import make_password, check_password hkey = make_password("123456") # pbkdf2_sha25615000MAjic... ret = check_password("123456","pbkdf2_sha25615000MAjic...") # True