Python simulates the Django framework instance and pythondjango framework
I. python web server implementation
Web development requires a web server first. For example, apache, but it is best to have a simple and convenient development server in the development stage,
It is easy to restart for debugging. After the development and debugging are completed, the code will be deployed to a mature, stable, and efficient web server.
#-*-Coding: UTF-8-*-from wsgiref import simple_server # define a simple web application def hello_app (environ, start_response) that outputs hello world and environment variables ): # output http header. text/plain indicates that it is plain text start_response ('2017 OK ', [('content-type', 'text/plain')]) # Prepare the output content = [] content. append ('Hello World') for key, value in environ. items (): content. append ('% s: % s' % (key, value) # output. According to the wsgi protocol, an iterator is returned, return ['\ n' if a list is returned '. join (content)] # construct the Development server Object, set the bound address and port, and pass the hello world application to its server = simple_server.make_server ('localhost', 8080, hello_app) # Start the Development server. serve_forever ()
After executing the above program, open the browser and visit a URL starting with http: // localhost: 8080 to see the content contained by environ.
(Part 1)
Ii. Basic Knowledge
The http protocol is used between the browser and the web application, which specifies the request and response format.
1. Request Packet (Http Request)
Requests mainly include request methods, request URLs, request headers, and request bodies.
The http request methods are defined as GET, POST, PUT, and DELETE, except that web requests initiated through a browser generally only involve GET and POST requests.
GET is generally used to obtain the server content. POST is similar to the modification content, such as PUT addition and DELETE deletion.
Generally, a POST request is initiated by submitting an html form. Redirection is required after the operation is successful.
In terms of the protocol, the biggest difference between HTTP requests and GET requests is that GET requests have no request body, whereas POST requests have. This means that the POST request can be used.
Send a large amount of data to the server, such as uploading files. Of course, the GET request can also pass parameters to the server through the URL itself and its parameters, such
Url? Arg1 = value & arg2 = value
The request header contains the description of the Request package. For example, encoding and package length.
2. Response packet (Http Response)
The http response packet format is simpler, including the status code, response header, and response body. The status code indicates the request result, such
200 indicates successful
404 indicates that the resource is not found
500 indicates a server error
301 indicates that the resource address has been changed and the client needs to jump to the address.
The response header is similar to the Request Header, including some descriptions. The response body is generally the output content, most of which are page html code.
3. Request Lifecycle
1. The web server packs the original http request to a certain extent and then submits it to the web application.
2. After processing, the web application returns data to the web server in a certain format.
3. The web server then packs the data into an http response package and returns it to the browser.
4. cgi
Cgi (common gateway interface) is an old protocol between a web server and a web application. In the cgi protocol,
The web server places various http request information in the environment variables of the cgi application, and the cgi application outputs its response header through standard output.
And the corresponding content to the web server.
The protocol used between the development server and the application is called wsgi. Similar to cgi, wsgi encapsulates requests into a key-value pair,
However, cgi is passed to the cgi application through environment variables, while wsgi uses the python dictionary object directly.
The first parameter environ of hello_app is the dictionary object containing the request information. The second parameter is a function, and the web application outputs the response content.
You must call it to output the status code and response header.
To process web requests and responses, use the webob module to process requests and responses. You must install the setuptools module and a package management tool, you can use this tool to automatically download required software packages, such as ubuntu app-get. The following url is http://pypi.python.org/pypi/setuptoolsinstallation example. You can directly enter "easy_install webob" in the command line to automatically download and install webob.
Easy to use:
>>># Import the Request object
>>> From webob import Request
>>> Environ = {}
>>># Use Request to wrap the environ dictionary
>>> Req = Request (environ)
Use a Request class to encapsulate environ, and then access environ through the attributes and methods of the Request object. Since a real environ dictionary can be obtained only in a web environment, webob provides a method to simulate simple web requests to facilitate testing in shell:
You can also use req to find other useful information.
You can also wrap the Response information through the Response object in the webob module.
The following uses the webob module to override the previous hello_app
#-*-Coding: UTF-8-*-from wsgiref import simple_serverfrom webob import Request, Response # A feature is added by the way, is based on the parameters passed after the URL # display the corresponding content def hello_app (request): content = [] # get the get request parameter content. append ('Hello % s' % request. GET ['name']) # output all environ variables for key, value in request. environ. items (): content. append ('% s: % s' % (key, value) response = Response (body =' \ n '. join (content) response. headers ['cont Ent-type '] = 'text/plain' return response # encapsulate the request and response def wsgi_wrapper (environ, start_response): Request = request (environ) response = hello_app (request) # The response object also implements the communication protocol with the wsgi server. # It can help us deal with the interaction with the web server. # This sentence is strange. What is the meaning of the object using parentheses .... Return response (environ, start_response) server = simple_server.make_server ('localhost', 8080, wsgi_wrapper) server. serve_forever ()
To make wsgi_wrapper more generic, you can design it as a decoration device:
#-*-Coding: UTF-8-*-from wsgiref import simple_serverfrom webob import Request, Response # Write wsgi_wrapperdef wsgi_wrapper (func): def new_func (environ, start_response ): request = Request (environ) response = func (request) return response (environ, start_response) new_func. _ name _ = func. _ name _ new_func. _ doc _ = func. _ doc _ return new_func # application @ wsgi_wrapperdef hello_app (request): content = [] content. append ('Hello % s' % request. GET ['name']) for key, value in request. environ. items (): content. append ('% s: % s' % (key, value) response = Response (body =' \ n '. join (content) response. headers ['content-type'] = 'text/plain 'return responseserver = simple_server.make_server ('localhost', 8080, hello_app) server. serve_forever ()
Iii. Template
Indeed, templates are still needed. You cannot always write long html code in Response.
The template engines in python mainly include mako, genshi, and jinjia.
MakoThe main feature is that the template can easily embed Python code, and the execution efficiency is first-class;
GenshiIt is characterized by xml-based, very easy-to-understand template syntax, which is a good choice for friends who love xhtml,
Python code can also be embedded to implement complex presentation logic;
JinjaAndGenshiIt also has simple template syntax, but does not depend on the xml format. It is also suitable for designers to directly create templates,
You can also embed Python code to implement complex presentation logic.
Use Mako here at http://pypi.python.org/pypi/mako. download Python setup. py install for installation.
Simple module example:
#-*-Coding: UTF-8-*-
Save it as a simple.html file, and then pass the data and name parameters to the template object, and then perform rendering, you can enter the html content
#-*-Coding: UTF-8-*-# import the template object from mako. template import Template # use the Template file name to construct the template object tmpl = Template (filename = '. /simple.html ', output_encoding = 'utf-8') # construct a simple Dictionary Filling template and print out print tmpl. render (name = 'python', data = {'A': 1, 'B': 2 })
Save it as the test_template.py file, and enter the content after running:
$ Python test_template.py
<Html>
The following is a reconstruction of the hello_app program:
1. Separate wsgi_wrapper into the general module utils. py:
# -*- coding: utf-8 -*-from webob import Requestdef wsgi_wrapper(func): def new_func(environ, start_response): request = Request(environ) response = func(request) return response(environ, start_response) new_func.__name__ = func.__name__ new_func.__doc__ = func.__doc__ return new_func
2. Completely separate hello_app to form a separate module controller. py:
#-*-Coding: UTF-8-*-from utils import wsgi_wrapperfrom webob import Responsefrom mako import Template # integrate the hello_app @ wsgi_wrapperdef hello_app (request) of the Template function ): tmpl = Template (filename = '. /simple.html ', output_encoding = 'utf-8') content = tmpl. render (name = request. GET ['name'], data = request. environ) return Response (body = content)
3. In this way, main. py becomes like this:
# -*- coding: utf-8 -*-from wsgiref import simple_serverfrom controller import hello_appserver = simple_server.make_server('localhost', 8080, hello_app)server.serve_forever()
Iv. ORM (Object Relation Mapping)
Finally, we need to work with the database as a web application.
Sqlalchemy is used here. It is an ORM (object-relational ing) library that provides ing between Python objects and relational databases. And Django models
The usage is similar. You can also use python code to create and operate database tables.
Sqlalchemy can also automatically map the inheritance of Python objects to implement eager loading and lazy loading, and can directly map the Model to custom
SQL statements, supporting n-plus databases, and so on. It can be said that sqlalchemy does not lose the powerful functions of Hibernate, but does not lose Python
Is concise and elegant.
Usage:
#-*-Coding: UTF-8-*-from sqlalchemy import * from sqlalchemy. orm import sessionmaker, scoped_sessionfrom sqlalchemy. ext. declarative import declarative_base # create a database engine. Here we directly use the database engine: sqlite that comes with Python2.5, # directly create a database named data in the current directory. database engine = create_engine ('sqlite: // data. db') # All Database Operations in sqlalchemy should be managed by a session # For details about the session, see: http://www.sqlalchemy.org/docs/05/session.htmlSession = scoped_session (sessionmaker (autocommit = False, autoflush = False, bind = engine) Base = declarative_base () class Dictionary (Base): # Name of the table corresponding to the relational database of the Python object _ tablename _ = 't_dictionary '# automatic definition, parameter meanings: database field name, field type, other options key = Column ('key', String (255), primary_key = True) value = Column ('value ', string (255) # create a database Base. metadata. create_all (engine) session = Session () for item in ['python', 'ruby', 'java']: # construct an object dictionary = Dictionary (key = item, value = item. upper () # Tell sqlalchemy to add the object to the database session. add (dictionary) # submit the session. Only database operations are performed here, and three records are added to the database session. commit () # query the data of the Dictionary object in the database for dictionary in session. query (Dictionary): print dictionary. key, dictionary. value
If you run the above Code twice, an error is reported. Why... Because the primary key inserted to the database already exists ....
In this way, it can be integrated into the previous controller. py file.
#-*-Coding: UTF-8-*-from utils import wsgi_wrapperfrom webob import Responsefrom mako. template import Template # import the common model module from model import Session, Dictionary @ wsgi_wrapperdef hello_app (request): session = Session () # query all Dictionary objects dictionaries = session. query (Dictionary) # convert the list into a Dictionary data = dict ([(dictionary. key, dictionary. value) for dictionary in dictionaries]) tmpl = Template (filename = '. /simple.html ', output_encoding = 'utf-8') content = tmpl. render (name = request. GET ['name'], data = data) return Response (body = content)
V. URL Distribution Control
Design different URLs for different resources. The client requests this URL, and the web application then locates and executes specific functions based on the URL requested by the user.
Providing a clean URL has many advantages:
1. Readability. You can use a URL to get a rough idea of what functions it provides.
2. Easy to remember and easy to input directly
3. Well-designed URLs are generally shorter and more refined, and are more friendly to search engines.
Use the selector module to process url ing
Http://pypi.python.org/pypi/selector, download the source file for python setup. py install
First, put the urls configuration separately in urls. py.
# -*- coding: utf-8 -*-from controller import hello_appmappings = [('/hello/{name}', {'GET':hello_app})]
Modify main. py
#-*-Coding: UTF-8-*-from wsgiref import simple_serverfrom urls import mappingsfrom selector import Selector # Build url distributor app = Selector (mappings) server = simple_server.make_server ('localhost ', 8080, app) server. serve_forever ()
Then, the name parameter can be obtained through environ ['wsgiorg. routing_args '] In hello_app,
However, wsgi_wrapper can further simplify the work of hello_app: directly parse the obtained parameters.
Passed as function parameter! Modify utils. py:
from webob import Requestdef wsgi_wrapper(func): def new_func(environ, start_response): request = Request(environ) position_args, keyword_args = environ.get('wsgiorg.routing_args', ((), {})) response = func(request, *position_args, **keyword_args) return response(environ, start_response) new_func.__name__ = func.__name__ new_func.__doc__ = func.__doc__ return new_func
Then hello_app can be changed to the following:
... @ Wsgi_wrapperdef hello_app (request, name = ''):... content = tmpl. render (name = name, data = data) return Response (body = content) execute main. py, access http: // localhost: 8080/hello/Python
Summary
The above implementation is similar to several main functional modules in the Django framework. I hope it will be helpful for your learning.