框架,即framework,特指爲解決一個開放性問題而設計的具備必定約束性的支撐結構,使用框架能夠幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來作表演。html

對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。前端

 1 import socket
 2 
 3 def handle_request(client):
 4 
 5     buf = client.recv(1024)
 6     client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
 7     client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))
 8 
 9 def main():
10 
11     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
12     sock.bind(('localhost',8001))
13     sock.listen(5)
14 
15     while True:
16         connection, address = sock.accept()
17         handle_request(connection)
18         connection.close()
19 
20 if __name__ == '__main__':
21 
22     main()
View Code

      最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。python

若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。jquery

      正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。web

在python中提供一個接口,幫咱們封裝socket,即wsgiref模塊:Web Server Gateway Interface。正則表達式

 1 from wsgiref.simple_server import make_server
 2  
 3  
 4 def RunServer(environ, start_response):
 5     start_response('200 OK', [('Content-Type', 'text/html')])
 6     return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]#返回的內容
 7  
 8  
 9 if __name__ == '__main__':
10     httpd = make_server('', 8000, RunServer)
11     print("Serving HTTP on port 8000...")
12     httpd.serve_forever()
整個application()函數自己沒有涉及到任何解析HTTP的部分,也就是說,底層代碼不須要咱們本身編寫,
咱們只負責在更高層次上考慮如何響應請求就能夠了。

application()函數必須由WSGI服務器來調用。有不少符合WSGI規範的服務器,咱們能夠挑選一個來用。

Python內置了一個WSGI服務器,這個模塊叫wsgiref    
    
    
application()函數就是符合WSGI標準的一個HTTP處理函數,它接收兩個參數:

        //environ:一個包含全部HTTP請求信息的dict對象;
        
        //start_response:一個發送HTTP響應的函數。

在application()函數中,調用:

start_response('200 OK', [('Content-Type', 'text/html')])

就發送了HTTP響應的Header,注意Header只能發送一次,也就是隻能調用一次start_response()函數。
start_response()函數接收兩個參數,一個是HTTP響應碼,一個是一組list表示的HTTP Header,每
個Header用一個包含兩個str的tuple表示。

一般狀況下,都應該把Content-Type頭髮送給瀏覽器。其餘不少經常使用的HTTP Header也應該發送。

而後,函數的返回值b'<h1>Hello, web!</h1>'將做爲HTTP響應的Body發送給瀏覽器。

有了WSGI,咱們關心的就是如何從environ這個dict對象拿到HTTP請求信息,而後構造HTML,
經過start_response()發送Header,最後返回Body。
注意:  

只要有請求,就會觸發RunServer函數,數據庫

environ封裝了客戶端發來的全部數據,
start_response封裝要返回給用戶的數據,好比:響應頭,狀態等

如今咱們訪問localhost:8000,顯示出來的都是hello,web,通常的網站的url都會有什麼/data,/index等,用來顯示不一樣的頁面內容,那咱們應該怎麼作呢?django

咱們設置斷點,進入調試模式,在運行瀏覽器能夠看到:瀏覽器

environ中有不少的參數,咱們找到一個叫作PATH_INFO的參數,那個就是顯示咱們url後面有什麼。緩存

這樣咱們就可以經過url進行判斷,而後進入相應的頁面:

from wsgiref.simple_server import make_server

def handle_index():
    return [bytes('<h1>Hello, Index!</h1>', encoding='utf-8'), ]
def hanle_date():
    return [bytes('<h1>Hello, Date!</h1>', encoding='utf-8'), ]

def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    currnet_url = environ['PATH_INFO'];
    if currnet_url =='/index':
        return handle_index()
    elif currnet_url =='/date':
        return hanle_date()
    else:
        return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ]


if __name__ == '__main__':
    httpd = make_server('', 8000, RunServer)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()

 

經過這個咱們完成了一些基本的操做。

那若是說url不少,咱們不可能一個一個去判斷吧,那咱們應該怎麼作呢?python中幾乎因此的web框架都是把全部的url放在一個列表中: 而後一類的url能夠經過正則表達式進行匹配

URL_DICT = {
    "/index":handle_index,
    "/date":handle_date,
}
def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    currnet_url = environ['PATH_INFO'];
    func = None
    if currnet_url in URL_DICT:
        func = URL_DICT[currnet_url]
    if func:
        return func()
    else:
        return [bytes('<h1>404,error!</h1>', encoding='utf-8'), ]

 咱們看上面的代碼,若是咱們把return裏的html放在一個html文件中,並放在View文件夾中;把handle_index等處理業務邏輯的函數寫在一個py文件中並放在Controller文件夾中。從數據庫讀取的方法放在Model文件夾中。

咱們須要html的時候就打開html文件f=open("html文件",mode="rb")而後read讀取就能夠了。

咱們須要用函數的時候就直接from Controller import 文件名,而後用文件名.函數名就能夠了。

咱們在html中想要用一些特殊的符號,數據從數據庫中獲取替換,也只要引入model文件家中的方法,讀出數據以後用replace函數替換符號和函數就能夠了。

MVC:

  Model數據庫    View模板文件    Controller業務處理

MTV:(Django是基於MTV的框架)

  Model數據庫    Template模板文件    View業務處理

2、Django

2.一、安裝Django

安裝:pip install django;

 

安裝完以後就多了一個可執行文件

2.二、建立django程序

方式一:經過命令行進入你要建立的目錄下,而後輸入命令 :django-admin.exe startproject mydjango

      

  方式二:經過pycharm直接建立Django程序

  

2.2.一、工程目錄

├── mysite
   └── mysite #這個纔是工程的包名。
     ├── __init__.py #代表mysite是一個包。 ├── settings.py #Django的配置文件,包括工程的app配置、數據庫配置、語言配置等。 ├── urls.py   #Django的調度者,根據不一樣的url映射到不一樣的視圖。 └── wsgi.py #WSGI是web server gateway interface,這個文件是使project符合這種協議的入口點(entry-point 指令變換點) ├── manage.py #與Django進行交互的命令行工具,好比後面根據model生成數據庫表結構、供開發使用的server等都是使用該工具,在manage.py的同級目錄使用python manage.py 能夠看到可使用的命令列表

2.3運行Django程序

方式一:進入程序目錄下經過命令行運行

python manage.py runserver (127.0.0.1:8001),默認端口號爲8000

方式二:在pycharm中運行

要注意要運行你的項目名稱,而不是manage.py或者是其餘的文件

若是要改運行的url和端口名:直接在host和port中設置就能夠了

2.四、建立app

一個project能夠又多個app,一個app能夠同時屬於多個project。經過如下命令建立一個app(在project目錄下)

建立app:  python manage.py startapp cmdb

2.4.一、app目錄

.
├── manage.py
├── django_learn
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── cmdb # app的根目錄
    ├── admin.py  #Django自帶了一個管理界面,這個文件能夠註冊model在界面中管理
    ├── apps.py   #配置當前app
    ├── __init__.py  #代表polls也是一個包
    ├── migrations   #用來初始化數據庫,在執行python manage.py makemigrations 的時候會自動生成一個文件在這裏
    │   └── __init__.py  #代表migrations也是一個包
    ├── models.py    #寫指定的類,經過命令能夠建立數據庫結構
    ├── tests.py     #寫測試代碼
    └── views.py     #業務代碼 Django映射urls.py裏面的url的時候,在views.py裏面查找對應的處理方法

3、練習--提交數據並展現(數據庫)

需求:

1.首先在django_learn文件夾下面建立templates文件夾用於存放html文件。

  若是在執行程序的時候,報找不到template的錯誤,那麼是settings裏面定義的路徑的問題。

2.在配置文件urls.py中指定路由關係:

 3.在cmdb這個app的view下定義用戶的處理邏輯: 

這裏django中有render模塊直接封裝了文件的打開讀取關閉的過程。傳入的index.html的路徑名是由django_learn下面的setting中的templates決定的(位置見1中ps):

4.導入靜態文件

  在mysite下面創建文件夾statics

  在templates下的html文件裏面添加引用

<script src="/static/jquery-1.12.4.js"></script> 

  在settings.py裏面定義靜態文件的路徑

STATIC_URL = '/static/' #做用:若是下面的tatics名字變了,仍然能夠用static來進行靜態文件的路徑拼接,
                        # 此時<script src="/statics/jquery-1.12.4.js"></script> = <script src="/static/jquery-1.12.4.js"></script> 
                        #目的是防止路徑變化致使前端人員引入靜態文件的路徑都得改,因此前端人員統一用/static進行拼接就好了
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'statics'),
)

  注意這裏靜態文件的URL要與src引入的路徑相匹配,而後經過http://127.0.0.1:8000/statics/jquery-1.12.4.js訪問JQuery成功。

 

5.咱們如今沒有作數據處理,咱們點擊提交:出現了CSRF的錯誤

若是咱們不想要這個錯誤的話能夠把settings中的代碼註釋了:

再次輸入127.0.0.1:8080/userInfo 就能夠訪問啦!!

 

6.上面表單的提交在頁面刷新之後就沒有了,由於內容是存放在緩存中的,如今,咱們須要將數據存放在數據庫當中,改寫以前的代碼。

  在models.py中建立userInfo的類:

class userinfo(models.Model):
    username=models.CharField(max_length=64)
    sex = models.CharField(max_length=64)
    email= models.CharField(max_length=64)

  在settings.py中註冊cmdb,而且查看DATABASES的設置:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'cmdb',  #必須先註冊,不然下面會報錯
]

  執行命令建立數據庫,表

D:\Python\mysite>python manage.py makemigrations
Migrations for 'cmdb':
  cmdb\migrations\0001_initial.py:
    - Create model UserInfo

D:\Python\mysite>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, cmdb, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying cmdb.0001_initial... OK
  Applying sessions.0001_initial... OK

  在用戶邏輯views.py中須要引入models操做數據庫

from cmdb import models
def userInfo(request):
    if request.method=="POST":
        u=request.POST.get("username",None)
        s=request.POST.get("sex",None)
        e=request.POST.get("email",None)
        # ---------表中插入數據方式一
        # info={"username":u,"sex":e,"email":e}
        # models.UserInfor.objects.create(**info)

        # ---------表中插入數據方式二
        models.userinfo.objects.create(
            username=u,
            sex=s,
            email=e
                    )
    userlist=models.userinfo.objects.all()
    # for i in userlist:
    #     print(i.username,i.sex,i.email)
    return render(request,"index.html",{"userlist":userlist})

 

  在顯示頁面上index.html顯示數據庫中提取的數據:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/userInfo" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性別<input type="text" name="sex"></p>
    <p>郵箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>

<h1>數據展現</h1>
<table border=1px>
        <tr>
        <td>姓名</td>
        <td>性別</td>
        <td>年齡</td>
    </tr>
    <tr>
        {% for i in userlist %}
        <td>{{i.username}}</td>
        <td>{{ i.sex }}</td>
        <td>{{ i.email }}</td>

    </tr>
        {% endfor %}
</table>
</body>
</html>

 #返回數據:HttpResponse("str")       return render(request,"html文件路徑","html中要替換的變量":USER_LIST)            return redirect("/只能填URL路徑")        

7.模板渲染

 模板語言:

--{{變量名}}
    def func(request):
      return render(request,'index.html',{'current_user':"alex"})
    index.html中
    <html>
    ........
      <body>
        <div>{{current_user}}</div>#這樣用alex替換了current_user
      </body>
    </html>
  --For循環
        userlist=[]
        def userInfo(request):
            if request.method=="POST":
                username=request.POST.get("username",None)
                sex=request.POST.get("sex",None)
                email=request.POST.get("email",None)
                user={"username":username,"sex":sex,"email":email}
                userlist.append(user)
            return render(request,"index.html",{"userlist":userlist})
    index.html中
    <html>
    ........
      <body>
            <table border=1px>
                <tr>
                    <td>姓名</td>
                    <td>性別</td>
                    <td>郵箱</td>
                </tr>
                <tr> {% for i in userlist %} <td>{{i.username}}</td>
                    <td>{{ i.sex }}</td>
                    <td>{{ i.email }}</td>
                </tr> {% endfor %} </table>
      </body>
    </html>
  --索引
    def func(request):
      return render(request,'index.html',{
               'current_user':"alex",
               'user_list':['xiaoming','liangliang']
               'user_dict':{'k1':'v1','k2':'v2'}})
    index.html中
    <html>
    ........
      <body>
        <a>{user_list.0/1}</a>

      </body>
    </html>
  --條件
    {%if age %}
      <a>有年齡</a>
    {% else %}
      <a>無年齡</a>
    {% endif %}
  --循環字典
    {%for k,row in dict.items%}#同時得到key和value
      <li>{{k}}-{{row}}</li>
    {%endfor%}
    {%for row in dict.keys%}#得到字典中的key
      <li>{{row}}</li>
    {%endfor%}
    {%for row in dict.values%}#得到字典中的value
      <li>{{row}}</li>
    {%endfor%}