Django Blog Series

Posted by richclever on Mon, 06 May 2019 13:05:03 +0200

Django Blog Series (I)

Preface

After learning Python for so long, I finally got to the Django framework. This can be said to be python's most famous web framework, so from today on, we will start to install the Django framework to use step-by-step learning. This series of blogs will not be as watery as the front end (flag), hoping to become a high-quality blog. Then this blog introduces the installation of Django and how to run the first Django application on the computer.

Installation of Django

Django is easy to install. pip installation command can be used on win and mac, pycharm installation can be used, or download files to install on command line using installation tools.

Next I install it on ubuntu as an example.

A dependency package pytz is also installed here. This is a third-party library for time zone conversion.

The PIP installation of other platforms is the same, but the corresponding pip of Python 3 should be selected to install, because the current version of Django does not support Python 2.

Installation of Virtual Environment

What is virtual environment

  • A copy version of the real python interpreter
  • Facts are valid and can exist independently and run interpreted python code
  • Multiple virtual environments can be copied on a computer

Why use virtual environment

  • Ensure the purity of the real environment
  • Multi-version coexistence of frameworks
  • Easy version iteration for frameworks
  • Reducing maintenance cost of multi-framework coexistence

Installing Virtual Environment

  1. Installation of Virtual Environment Library through pip

Because I downloaded it before, it shows that the request has been completed directly, followed by the absolute path of the installation.

  1. Go to the target folder

This folder is the folder that you use to save the virtual environment. Once you are sure of it, don't change it easily.

This py3-env1 is a pure virtual environment created.

  1. Creating a Pure Virtual Environment
Virtual environment name (py3-env2)
  1. Terminal Start Virtual Environment
cd py3-env1\Scripts
activate
  1. python development environment in virtual environment
python3
  1. Turn off the virtual environment
deactivate
  1. Development Configuration of Pycharm
Add: Create project - > Project Interpreter - > Existing interpreter - > Virtualenv Environment | System Interpreter - > python.exe under target path
 Delete: Setting - > Project - > Project Interpreter - > Show All

mac computer from step three to the last step

understand

# Create a non-pure environment:
# - virtualenv-clone Local Environment Virtual Environment Name
# Mac Configuration Terminal, Running Virtual Environment at Terminal
 # Settings in the. bash_profile (no need to be created manually) file in the user root directory
 # alias terminal instruction name (env-py3)='/Library/Virtualenv/virtual environment name/bin/python 3'
# alias terminal instruction name (env-pip3)='/Library/Virtualenv/virtual environment name/bin/pip3'

HTTP protocol

Because the application layer of Django framework adopts HTTP protocol, it is necessary to understand HTTP protocol.

What is HTTP Protocol

  • HTTP (HyperText Transport Protocol) is a hypertext transmission protocol, and HTTPS belongs to HTTP protocol, S stands for security.
  • Based on the application layer protocol based on TCP/IP protocol, the underlying implementation is still socket.
  • Based on Request-Response Mode: Communication must start from the client, and the server will respond to the client when it receives it.
  • Stateless: The protocol does not save any communication status and any data.
  • Connectionless: A connection only completes one request-response, and the connection will be disconnected immediately after the request-response is completed.

Working Principle of HTTP

An HTTP connection is called a transaction, and the process can be divided into four steps.

  1. Connection between client and server
  2. A client requests an HTTP protocol in a specified format
  3. When the server receives the request, it responds to a response in the specified format of the HTTP protocol.
  4. The client presents the response of the server to the user

HTTP status code

  • 1 start:

  • 2 start:

  • 3 start:

  • 4 start:

  • 5 start:

Request message

# Request line request header requester
'''
POST / HTTP/1.1\r\n
Host: 127.0.0.1:8001\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8\r\n
\r\n
usr=abc&pwd=123
'''

response message

# Response Row Response Head Response Body
'''
HTTP/1.1 200 OK\r\n
Content-type:text/html\r\n
\r\n
Login Success
'''

Interaction with browsers using native socket s

directory structure

01_socket
    - 01_client.html: The front desk accesses the back-end pages through the form
    - 01_login.html: The background test renders the login page to the front desk
    - 01_index.html: The home page rendered to the front desk by the background test
    - 01_server.py: Background server file

Because the client side of B/S architecture has been written by browser, it only needs to pay attention to the server side.

Server-side code

from socket import socket

# Set up the response header (including the response line)
RESP_HEADER = b'HTTP/1.1 200 OK\r\nContent-type:text/html;charset=utf-8\r\n\r\n' # Two consecutivern denote the end of the response head

# Setting up server socket related information
server = socket()
server.bind('', 8080) # An empty string represents the bound native
server.listen(5)
print(('Services: http://localhost:8080'))

while True:
    # Get the request sent in http protocol
    client, addr = server.accept()
    data = client.recv(1024)
    # The data message contains the request header body of the request line
    print(data)
    client.send(RESP_HEADER)
    
    # / Index => Response Home Page
    # / login => login page
    # Error => 404
    # Data data, byte form => string form
    strData = str(data, encodeing)
    
    # Parse the requested data and get the routing
    my_route = strData.split('\r\n')[0].split(' ')[1]
    
    # Background routing is not set up, it is handled by 404.
    dt = b'404'
    
    # Setted routing returns the page file of the response
    if my_route == '/index':
        with open('index Page path', 'rb') as f:
            dt = f.read()
    if my_route == '/login':
        with open('login Page path', 'rb') as f:
            dt = f.read()
            
    # / favicon.ico This request is to request the label icon from the background
    if my_route == '/favicon.ico':
        with open('favicon.ico', 'rb') as f:
            dt = f.read()
    # Server Sends Response Body
    client.send(dt)
    # A loop, representing a response, that is, the completion of a transaction, closes the http request connection
    client.close()

Modify the returned data and improve the response body

# Character string
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'\r\n')
client.send(b'Normal Socket Web')
# html code, request header to set support html code
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
client.send(b'<h1>Normal Socket Web</h1>')
# html file (the same directory creates an index.html page)
client.send(b'HTTP/1.1 200 OK\r\n')
client.send(b'Content-type:text/html\r\n')
client.send(b'\r\n')
# Reading Pages by File Mode
with open('01_index.html', 'rb') as f:
    dt = f.read()
client.send(dt)

Expand

Modify receiving data to simulate background routing

# Analysis of received data
data = client.recv(1024)
# Ensure that the received data is processed as a string as follows
data = str(data, encoding='utf-8')
# Split out address bits
route = data.split('\r\n')[0].split(' ')[1]
# Match addresses and respond differently
if route == '/index':
    with open('01_index.html', 'rb') as f:
        dt = f.read()
elif route == '/login':
    with open('01_login.html', 'rb') as f:
        dt = f.read()
else:
    dt = b'404'
client.send(dt)

Frame evolution

directory structure

02_frame
    -- favicon.ico
    -- index.html
    -- manage.py

manage.py

import socket
import pymysql
# Response head
RESP_HEADER = b'HTTP/1.1 200 OK\r\nContent-type:text/html\r\n\r\n'

# Request processing
def index():
    # Read files in bytes
    with open('index.html', 'rb') as f:
        dt = f.read()
    return dt
def ico():
    with open('favicon.ico', 'rb') as f:
        dt = f.read()
    return dt
def user():
    # Database operation
    conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
    cur = conn.cursor(pymysql.cursors.DictCursor)
    cur.execute('select * from user')
    users = cur.fetchall()
    print(users)
    users = '''%d:%s
    %d:%s''' % (users[0]['id'], users[0]['name'], users[1]['id'], users[1]['name'])
    return users.encode('utf-8')

# Route setting
urls = {
    # Request path corresponds to request processing function one by one
    '/index': index,
    '/favicon.ico': ico,
    '/user': user
}

# Set socket
def serve(host, port):
    server = socket.socket()
    server.bind((host, port))
    print('start:http://' + host + ':' + str(port))
    server.listen(5)
    while True:
        sock, addr = server.accept()
        data = sock.recv(1024)
        data = str(data, encoding='utf-8')
        print(data)
        route = data.split('\r\n')[0].split(' ')[1]

        resp = b'404'
        if route in urls:
            resp = urls[route]()

        sock.send(RESP_HEADER)
        sock.send(resp)
        sock.close()

# Start service
if __name__ == '__main__':
    serve('127.0.0.1', 8002)

Project evolution

directory structure

03_proj
    -- template
        -- index.html
        -- user.html
    favicon.ico
    start.py
    urls.py
    views.py

index.html

<h1>{{ name }}</h1>

user.html

<table border="1">
    <tr>
        <th>id</th>
        <th>name</th>
        <th>password</th>
    </tr>
    {% for user in users%}
    <tr>
        <td>{{user.id}}</td>
        <td>{{user.name}}</td>
        <td>{{user.password}}</td>
    </tr>
    {% endfor %}
</table>

start.py

from wsgiref.simple_server import make_server
from urls import urls


def app(env, response):
    print(env)
    # Setting up the response head
    response("200 OK", [('Content-type', 'text/html')])
    route = env['PATH_INFO']
    print(route)
    data = urls['error']()
    if route in urls:
        data = urls[route]()
    # Returns the binary responder
    return [data]


if __name__ == '__main__':
    server = make_server('127.0.0.1', 8003, app)
    print('start:http://127.0.0.1:8003')
    server.serve_forever()

urls.py

from views import *
urls = {
    '/index': index,
    '/favicon.ico': ico,
    '/user': user,
    'error': error
}

views.py

import pymysql
# Using jinja2 to render the template and transfer background data to the front desk
from jinja2 import Template

def index():
    with open('templates/index.html', 'r') as f:
        dt = f.read()
    tem = Template(dt)
    resp = tem.render(name='homepage')
    return resp.encode('utf-8')

def ico():
    with open('favicon.ico', 'rb') as f:
        dt = f.read()
    return dt

def user():
    # Database operation
    conn = pymysql.connect(host='127.0.0.1', port=3306, db='django', user='root', password='root')
    cur = conn.cursor(pymysql.cursors.DictCursor)
    cur.execute('select * from user')
    users = cur.fetchall()
    print(users)

    with open('templates/user.html', 'r') as f:
        dt = f.read()
    tem = Template(dt)
    resp = tem.render(users=users)

    return resp.encode('utf-8')

def error():
    return b'404'

Topics: Python socket Django pip