Django opening - Web Applications

Make up a Web application


The next aim of our study was to develop a Web application, a Web application is based on B / S architecture, where B refers to the browser, it is responsible for sending a request message to the S side, while the S end will be according to the received return the data request information corresponding to the browser, to be emphasized that is: S end by two parts and application server configuration, as shown:
figure: Web application composition

Two develop a Web application

We need to develop a browser (ie, the nature of the client socket), only to end development of S, S end of the essence is to use socket implementations, as follows

# S端
import socket

def make_server(ip, port, app):  # 代表server
    sock = socket.socket()
    sock.bind((ip, port))
    sock.listen(5)
    print('Starting development server at http://%s:%s/' %(ip,port))
    while True:
        conn, addr = sock.accept()

        # 1、接收浏览器发来的请求信息
        recv_data = conn.recv(1024)
        # print(recv_data.decode('utf-8'))

        # 2、将请求信息直接转交给application
        res = app(recv_data)

        # 3、向浏览器返回消息(此处并没有按照http协议返回)
        conn.send(res)
        
        conn.close()

def app(environ):  # 代表application
    # 处理业务逻辑
    return b'hello world'

if __name__ == '__main__':
    make_server('127.0.0.1', 8008, app)  # 在客户端浏览器输入:http://127.0.0.1:8008 会报错(注意:请使用谷歌浏览器)

Currently S terminal has normally received can be sent to the browser request message, but the browser receives a response message reply to the S terminal b'hello world 'not being able to resolve properly, because the terminal between the browser and send and receive messages by default S application layer protocol used is HTTP, the browser's default message format will be in accordance with the provisions of the HTTP protocol, while the S side also have to follow the format back to the message of the HTTP protocol, so then we detail HTTP protocol
HTTP protocol detailed link address: https://www.cnblogs.com/Du704/p/11713916.html

S side revision: HTTP protocol processing request message, and the reply message according to the HTTP protocol format

# S端
import socket

def make_server(ip, port, app): # 代表server
    sock = socket.socket()
    sock.bind((ip, port))
    sock.listen(5)
    print('Starting development server at http://%s:%s/' %(ip,port))
    while True:
        conn, addr = sock.accept()

        # 1、接收并处理浏览器发来的请求信息
        # 1.1 接收浏览器发来的http协议的消息
        recv_data = conn.recv(1024)

        # 1.2 对http协议的消息加以处理,简单示范如下
        ll=recv_data.decode('utf-8').split('\r\n')
        head_ll=ll[0].split(' ')
        environ={}
        environ['PATH_INFO']=head_ll[1]
        environ['method']=head_ll[0]

        # 2:将请求信息处理后的结果environ交给application,这样application便无需再关注请求信息的处理,可以更加专注于业务逻辑的处理
        res = app(environ)

        # 3:按照http协议向浏览器返回消息
        # 3.1 返回响应首行
        conn.send(b'HTTP/1.1 200 OK\r\n')
        # 3.2 返回响应头(可以省略)
        conn.send(b'Content-Type: text/html\r\n\r\n')
        # 3.3 返回响应体
        conn.send(res)

        conn.close()

def app(environ): # 代表application
    # 处理业务逻辑
    return b'hello world'

if __name__ == '__main__':
    make_server('127.0.0.1', 8008, app)

At this point, after the restart S terminal, and then the client browser enter: http://127.0.0.1:8008 can see hello world a normal result.

Not only can we respond to such an ordinary character hello world, can also mixed html tags, the browser after receiving the message will parse html tags to be rendered

# S端
import socket

def make_server(ip, port, app): 
    sock = socket.socket()
    sock.bind((ip, port))
    sock.listen(5)
    print('Starting development server at http://%s:%s/' %(ip,port))
    while True:
        conn, addr = sock.accept()
        
        recv_data = conn.recv(1024)
        ll=recv_data.decode('utf-8').split('\r\n')
        head_ll=ll[0].split(' ')
        environ={}
        environ['PATH_INFO']=head_ll[1]
        environ['method']=head_ll[0]

        res = app(environ)

        conn.send(b'HTTP/1.1 200 OK\r\n')
        conn.send(b'Content-Type: text/html\r\n\r\n')
        conn.send(res)

        conn.close()

def app(environ):
    # 返回html标签
    return b'<h1>hello web</h1><img src="https://www.baidu.com/img/bd_logo1.png"></img>'

if __name__ == '__main__':
    make_server('127.0.0.1', 8008, app)

Furthermore, we can also return a file, for example timer.html, reads as follows

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>{{ time }}</h2>
</body>
</html>

End procedure is as follows S

# S端
import socket

def make_server(ip, port, app): # 代表server
    sock = socket.socket()
    sock.bind((ip, port))
    sock.listen(5)
    print('Starting development server at http://%s:%s/' %(ip,port))
    while True:
        conn, addr = sock.accept()

        recv_data = conn.recv(1024)
        ll=recv_data.decode('utf-8').split('\r\n')
        head_ll=ll[0].split(' ')
        environ={}
        environ['PATH_INFO']=head_ll[1]
        environ['method']=head_ll[0]

        res = app(environ)

        conn.send(b'HTTP/1.1 200 OK\r\n')
        conn.send(b'Content-Type: text/html\r\n\r\n')
        conn.send(res)

        conn.close()

def app(environ):
    # 处理业务逻辑:打开文件,读取文件内容并返回
    with open('timer.html', 'r', encoding='utf-8') as f:
        data = f.read()
    return data.encode('utf-8')

if __name__ == '__main__':
    make_server('127.0.0.1', 8008, app)

S end is above the browser returns are static pages (fixed content), we can also return dynamic page (content varies)

# S端
import socket

def make_server(ip, port, app): # 代表server
    sock = socket.socket()
    sock.bind((ip, port))
    sock.listen(5)
    print('Starting development server at http://%s:%s/' %(ip,port))
    while True:
        conn, addr = sock.accept()

        recv_data = conn.recv(1024)
        ll=recv_data.decode('utf-8').split('\r\n')
        head_ll=ll[0].split(' ')
        environ={}
        environ['PATH_INFO']=head_ll[1]
        environ['method']=head_ll[0]

        res = app(environ)

        conn.send(b'HTTP/1.1 200 OK\r\n')
        conn.send(b'Content-Type: text/html\r\n\r\n')
        conn.send(res)

        conn.close()

def app(environ):
    # 处理业务逻辑
    with open('timer.html', 'r', encoding='utf-8') as f:
        data = f.read()

    import time
    now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    data = data.replace('{{ time }}', now)  # 字符串替换
    return data.encode('utf-8')

if __name__ == '__main__':
    make_server('127.0.0.1', 8008, app) # 在浏览器输入http://127.0.0.1:8008,每次刷新都会看到不同的时间

The origin of three Web Framework

In summary case we can find a rule, in the development of the S terminal, server function is complex and fixed (processing socket message transceiver and http protocol), and app business logic, but not the same (different software should have different business logic), and repeat the development of complex fixed server is meaningless, there is a module to help us wsgiref written server functionality, so we just need to focus on the function of the app to write

# wsgiref实现了server,即make_server
from wsgiref.simple_server import make_server 

def app(environ, start_response): # 代表application 
    # 1、返回http协议的响应首行和响应头信息
    start_response('200 OK', [('Content-Type', 'text/html')])
    
    # 2、处理业务逻辑:根据请求url的不同返回不同的页面内容
    if environ.get('PATH_INFO') == '/index':
        with open('index.html','r', encoding='utf-8') as f:
            data=f.read()
    elif environ.get('PATH_INFO') == '/timer':
        with open('timer.html', 'r', encoding='utf-8') as f:
            data = f.read()
        import time
        now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        data = data.replace('{{ time }}', now)  # 字符串替换
    else:
        data='<h1>Hello, web!</h1>'
    
    # 3、返回http响应体信息,必须是bytes类型,必须放在列表中
    return [data.encode('utf-8')]

if __name__ == '__main__':
    # 当接收到请求时,wsgiref模块会对该请求加以处理,然后后调用app函数,自动传入两个参数:
    # 1 environ是一个字典,存放了http的请求信息
    # 2 start_response是一个功能,用于返回http协议的响应首行和响应头信息
    s = make_server('', 8011, app) # 代表server
    print('监听8011')
    s.serve_forever() # 在浏览器输入http://127.0.0.1:8011/index和http://127.0.0.1:8011/timer会看到不同的页面内容

timer.html already exist, the new index.html page reads as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>主页</h1>
</body>
</html>

The example above app needs to be returned when dealing with business logic url address different depending on the content of the page, as more and more url address, you need to write a bunch determine if the code is not clear enough, a high degree of coupling, so we make the following optimization

# 处理业务逻辑的函数
def index(environ):
    with open('index.html', 'r', encoding='utf-8') as f:
        data = f.read()
    return data.encode('utf-8')


def timer(environ):
    import datetime
    now = datetime.datetime.now().strftime('%y-%m-%d %X')
    with open('timer.html', 'r', encoding='utf-8') as f:
        data = f.read()
    data = data.replace('{{ time }}', now)
    return data.encode('utf-8')


# 路径跟函数的映射关系
url_patterns = [
    ('/index', index),
    ('/timer', timer),
]

from wsgiref.simple_server import make_server


def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])

    # 拿到请求的url并根据映射关系url_patters执行相应的函数
    reuqest_url = environ.get('PATH_INFO')
    for url in url_patterns:
        if url[0] == reuqest_url:
            data = url[1](environ)
            break
    else:
        data = b'404'

    return [data]


if __name__ == '__main__':
    s = make_server('', 8011, app)
    print('监听8011')
    s.serve_forever()

With increasing complexity of business logic, business logic processing functions and the mapping of relationships url_patterns will continue to increase, this time still put all the code into a file, readability and scalability will become program very poor, so we should split the existing code to a different file
illustration:

mysite # 文件夹
    ├── app01 # 文件夹
    │   └── views.py
    ├── mysite # 文件夹
    │   └── urls.py
    └── templates # 文件夹
    │   ├── index.html
    │   └── timer.html
    ├── main.py

views.py reads as follows:

# 处理业务逻辑的函数
def index(environ):
    with open('templates/index.html', 'r',encoding='utf-8') as f: # 注意文件路径
        data = f.read()
    return data.encode('utf-8')

def timer(environ):
    import datetime
    now = datetime.datetime.now().strftime('%y-%m-%d %X')
    with open('templates/timer.html', 'r',encoding='utf-8') as f: # 注意文件路径
        data = f.read()
    data=data.replace('{{ time }}',now)
    return data.encode('utf-8')

urls.py reads as follows:

# 路径跟函数的映射关系
from app01.views import * # 需要导入views中的函数

url_patterns = [
    ('/index', index),
    ('/timer', timer),
]

main.py reads as follows:

from wsgiref.simple_server import make_server
from mysite.urls import url_patterns  # 需要导入urls中的url_patterns


def app(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])

    # 拿到请求的url并根据映射关系url_patters执行相应的函数
    reuqest_url = environ.get('PATH_INFO')
    for url in url_patterns:
        if url[0] == reuqest_url:
            data = url[1](environ)
            break
    else:
        data = b'404'

    return [data]


if __name__ == '__main__':
    s = make_server('', 8011, app)
    print('监听8011')
    s.serve_forever()

So far, we have for the development of a custom application framework, so that the nature of the framework is a collection of a series of functions, different functions into different files. With this framework, allows us to focus on writing business logic, greatly improves the efficiency of the development of web applications (web application development framework can be referred to as web framework), for example, we add a business logic required to: Browse http://127.0.0.1:8011/home able to access input page home.html, the base frame on the development of specific steps as follows:
step a: Add home.html templates folder at
step two: urls .py the url_patterns in a new relationship mapping

url_patterns = [
    ('/index', index),
    ('/timer', timer),
    ('/home', home), # 新增的映射关系
]

Step Three: In views.py in a new function named home

def home(environ):
    with open('templates/home.html', 'r',encoding='utf-8') as f: 
        data = f.read()
    return data.encode('utf-8')

We have since limited framework functions defined in Python we can use developed by others, more powerful Django framework

Installation and use of four framework Django

When using the Django framework for developing web applications, developers rely on the same stage wsgiref Server module to achieve the function, we use the Django framework for rapid application development

4.1 Installation

Mainstream version of Django framework for companies to develop 1.11.x version, the latest version 2.x, we mainly on the 1.11 version, the new features will also involve the 2.x

pip3 install django==1.11.18 # 在命令行执行该命令

4.2

4.2.1 quickly create and launch Django project


If you are using our self-defined framework for developing web applications, you need to generate a series of pre-basic framework document contains, and then developed on this basis.
If you are using the Django framework to develop web applications, also you need to generate a series of pre-basic document that contains the Django framework, and to develop on this basis.
But more convenient Django framework is that it has provided us with a series of commands to help us to quickly generate a series of basic documents

# 在命令行执行以下指令,会在当前目录生成一个名为mysite的文件夹,该文件夹中包含Django框架的一系列基础文件
django-admin startproject mysite

Create a function module

cd mysite # 切换到mysite目录下,执行以下命令
python manage.py startapp app01 # 创建功能模块app01,此处的startapp代表创建application下的一个功能模块。例如我们要开发application是京东商城,京东商城这个大项目下有一个订单管理模块,我们可以将其命名为app01

run

python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001 会看到Django的欢迎页面。

4.2.2 Django project directory structure


FIG cut tree (directory according to the following screenshot)

mysite # 文件夹
    ├── app01 # 文件夹
    │   └── migrations # 文件夹
    │   └── admin.py
    │   └── apps.py
    │   └── models.py
    │   └── tests.py
    │   └── views.py
    ├── mysite # 文件夹
    │   └── settings.py
    │   └── urls.py
    │   └── wsgi.py
    └── templates # 文件夹
    ├── manage.py

The key document presents

-manage.py---项目入口,执行一些命令
-项目名
    -settings.py  全局配置信息
    -urls.py      总路由,请求地址跟视图函数的映射关系
-app名字
    -migrations   数据库迁移的记录
    -models.py    数据库表模型
    -views.py     处理业务逻辑的函数,简称视图函数

4.2.3 Pycharm create a Django project

4.2.4 a simple exemplary implementation based Django

(1)url.py
from django.contrib import admin
from django.conf.urls import url
#导入views模块
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    
    # r'^index/$' 会正则匹配url地址的路径部分
    url(r'^index/$',views.index), # 新增地址http://127.0.0.1:8001/index/与index函数的映射关系
]
(2) View
from django.shortcuts import render

# 必须定义一个request形参,request相当于我们自定义框架时的environ参数
def index(request):
    import datetime
    now=datetime.datetime.now()
    ctime=now.strftime("%Y-%m-%d %X")

    return render(request,"index.html",{"ctime":ctime}) # render会读取templates目录下的index.html文件的内容并且用字典中的ctime的值替换模版中的{{ ctime }}
(3) template

New index.html file in the templates directory

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>当前时间:{{ ctime }}</h4>

</body>
</html>

test:

python manage.py runserver 8001 # 在浏览器输入:http://127.0.0.1:8001/index/ 会看到当前时间。

Stratification and request life cycle 4.2.5 Django framework

In summary, we Django framework is to develop application, the application is essentially working process returns different data depending on the request, the frame Django this process is subdivided into the following four working to achieve
a routing layer (depending on address functions perform different views, see the urls.py)
2, layer view (view definition processing business logic function, see the views.py)
. 3, the model layer (dealing with databases, explain the models.py)
. 4, the template layer (html file to be returned to the browser, see Templates)
Django request lifecycle

which embodies the idea of one kind of decoupling, let's start details of each layer

Guess you like

Origin www.cnblogs.com/Du704/p/11713951.html