Get started with python Programming quickly (continuous update...)
python actual combat online bookstore project (Flask technology point More))
1, Create project
1. Prepare project code warehouse
1. Source hosting website: Code cloud( https://gitee.com/ )
2. Create source code remote warehouse: fisher
2. Clone project code warehouse
1. Click VCs - > get from version control
2. Click [Log in to GitHub] and enter the user name and password to log in:
3. After login, click Clone. Git cloning complete.
3.pipenv create virtual environment
settings->python interperter->show all->+(venv)->ok
Rewrite and open terminal to enter the virtual environment
2, Instantiation and startup of flash
1. Directory structure
2.Flask installation
pip install flask==0.10.1
3.fisher.py
from flask import Flask app = Flask(__name__) @app.route('/hello/') def hello(): return 'Hello, fisher' app.run()
4. Flash configuration file
setting.py
# All letters should be capitalized # The system has a DEBUG default value of False DEBUG = True HOST = "0.0.0.0" PORT = 8090
Use app.init.py
# Get profile app.config.from_object(app.setting) app.config['DEBUG']
5.if name = "main"
Ensure that app.run will not start again, single thread. Production nginx+uwsgi
threaded=True
Single process multithreading
6. Register routing
from flask import Flask app = Flask(__name__) @app.route('/hello/') def hello(): return 'Hello, fisher' app.run()
Method 1. Compatible with slash
@app.route('/hello/')
Method 2
app.add_url_rule('/hello', view_func=hello)
7. Return string
headers = { 'content-type':'text/plain' } response = make_response('<html></html>', 404) response.headers = headers return response
8. Redirection
def hello(): # 1/0 # The view function returns response # status code 200 301 404 # content-type http headers # content-type = text/html headers = { # 'content-type':'text/plain' # 'content-type': 'application/json' 'location':'http://www.baidu.com' } response = make_response('<html></html>', 301) response.headers = headers return response
2, Application, blueprint and view functions
0. Hierarchical relationship of flask
The top layer of Flask is the app core object
Many blueprints can be inserted into this core object. This blueprint cannot exist alone. The app must be inserted into the app as a plug-in board
On each blueprint, you can register many static files, views, functions, and templates
A business module can be used as a blueprint, such as book and user. You can register the view function on the blueprint and insert the app. So as to achieve the purpose of previous sub documents
The previous book.py is placed under the app/web / path, which takes into account the blueprint. App belongs to the whole flash application layer. The web is a blueprint
1. Write model
a. Installation
Install PIP install flash Sqlalchemy
Install pip install cymysql
b. Map model to database
SQLALCHEMY_DATABASE_URI = 'mysql+cymysql://root:root@localhost:3306/fisher'
db.init_app(app) db.create_all(app=app)
a. Define base model
from datetime import datetime from contextlib import contextmanager from sqlalchemy import Column, Integer, SmallInteger from flask import current_app from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy, BaseQuery __all__ = ['db', 'Base'] class SQLAlchemy(_SQLAlchemy): @contextmanager def auto_commit(self, throw=True): try: yield self.session.commit() except Exception as e: self.session.rollback() current_app.logger.exception('%r' % e) if throw: raise e class Query(BaseQuery): def filter_by(self, **kwargs): if 'status' not in kwargs.keys(): kwargs['status'] = 1 return super(Query, self).filter_by(**kwargs) db = SQLAlchemy(query_class=Query) # class BaseMixin(object): # def __getitem__(self, key): # return getattr(self, key) class Base(db.Model): __abstract__ = True create_time = Column('create_time', Integer) status = Column(SmallInteger, default=1) def __init__(self): self.create_time = int(datetime.now().timestamp()) @property def create_datetime(self): if self.create_time: return datetime.fromtimestamp(self.create_time) else: return None def delete(self): self.status = 0 def set_attrs(self, attrs): for key, value in attrs.items(): if hasattr(self, key) and key != 'id': setattr(self, key, value) class BaseNoCreateTime(db.Model): __abstract__ = True status = Column(SmallInteger, default=1)
b. Define book model
import json from sqlalchemy import Column, String from sqlalchemy import Integer from app.models.base import Base class Book(Base): """ Some attribute definitions are repetitive, and metaclasses can solve this problem """ __tablename__ = 'book' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) _author = Column('author', String(30), default='Unknown') binding = Column(String(20)) publisher = Column(String(50)) price = Column(String(20)) pages = Column(Integer) pubdate = Column(String(20)) isbn = Column(String(15), nullable=False, unique=True) summary = Column(String(1000)) image = Column(String(50)) @property def author(self): return self._author if not self._author else json.loads(self._author) @author.setter def author(self, value): if not isinstance(value, str): self._author = json.dumps(value, ensure_ascii=False) else: self._author = value @property def author_str(self): return '' if not self._author else ','.join(self.author)
2. Code Standardization
a.app/init.py initial app
from flask import Flask from app.models.base import db # Initial app def create_app(): app = Flask(__name__) app.config.from_object("app.secure") app.config.from_object("app.setting") # print(app.config["HOST"]) register_blueprint(app) db.init_app(app) db.create_all(app=app) return app
b. Modified fisher.py
from app import create_app app = create_app() if __name__ == "__main__": print("id by" + str(id(app)) + "of app start-up") app.run()
c. Register the view function in the blueprint (app.splider/yushu_book.py)
from flask import jsonify, request from . import web from app.libs.helper import is_isbn_or_key from app.spider.yushu_book import YuShuBook # Instantiation blueprint # The first parameter is the module name of the blueprint # apply name # web = Blueprint('web', __name__) from ..forms.book import SearchForm @web.route("/book/search/") def search(): """ Search book routing :param q: keyword OR isbn :param page: Page number :?q=1212&page=1 """ form = SearchForm(request.args) if form.validate(): q = form.q.data.strip() page = form.page.data print('==================================', q, page) isbn_or_key = is_isbn_or_key(q) if isbn_or_key == 'isbn': result = YuShuBook.search_by_isbn(q) else: result = YuShuBook.search_by_key(q) return jsonify(result) else: return jsonify({'msg':'Parameter verification failed'})
d. Blueprints cannot replace app applications. After registering view functions in blueprints, you need to insert blueprints into app(app/init.py)
def register_blueprint(app): from app.web import web app.register_blueprint(web)
e. Register the view function in the blueprint and put it into web/init
from flask import Blueprint web = Blueprint('web', __name__) from app.web import book
3.Request object
The url request path we defined earlier is rest style / book / search / /, and flask will automatically map the value in < > to the parameters of the view function method.
However, if you need to pass in method parameters as Request parameters. You need to use the Request built in flash. The Request contains the details of the HTTP Request, such as param, method, url, remote ip, etc.
q = request.args['q']
4 WTForms parameter validation
WTForms is an excellent parameter validation framework. Parameter validation can be pulled out of a module. Decouple from business code.
Importing WTForms using pip
pip install wtforms
To use wtforms, you need to customize a class, inherit the Form class provided by wtforms, and then define the parameter verification rule app/forms/book.py
from wtforms import Form, StringField, IntegerField from wtforms.validators import Length, NumberRange, DataRequired class SearchForm(Form): # Parameter verification rules: # 1. The defined attribute name Q and page should have the same name as the parameter to be verified # 2. Select different Field classes for instantiation according to the parameter types to be passed in # 3. Pass in an array as validation rule validators # 4. Default values can be set q = StringField(validators=[DataRequired(), Length(min=1, max=30,message="Query keyword length must be within 1-30 between")], ) page = IntegerField(validators=[NumberRange(min=1, max=99)], default=1)
5.Flask obtains data from API
a.helper.py(app.libs)
def is_isbn_or_key(word): """ judge word yes isbn Number or query keyword key isbn isbn13 By 13 zeros-9 In digital composition isbn10 Table 0 from 10-9 The table is composed of groups of numbers, and the middle may contain' - ' :param word: :return: key or isbn """ isbn_or_key = 'key' if len(word) == 13 and word.isdigit(): isbn_or_key = 'isbn' short_word = word.replace('-', '') if '-' in word and len(short_word) == 10 and short_word.isdigit(): isbn_or_key = 'isbn' return isbn_or_key
b.requests is a simplified means of sending http requests and codes
import requests class HTTP: @staticmethod def get(url, return_json=True): """ send out get request :param url: Request path :param return_json: Return json Formatted results :return: """ # r is an encapsulation of the result of this HTTP request call. It is not the result we want directly, but the content we want to return r = requests.get(url) if r.status_code != 200: return {} if return_json else '' return r.json() if return_json else r.text
c.app.spider/yushu_book.py
from flask import current_app from app.libs.httper import HTTP class YuShuBook: search_by_isbn_url = "http://t.yushu.im/v2/book/search/isbn/{}" search_by_key_url = "http://t.yushu.im/v2/book/search?q={}&count={}&start={}" @classmethod def search_by_isbn(cls, isbn): url = cls.search_by_isbn_url.format(isbn) return HTTP.get(url) @classmethod def search_by_key(cls, keyword, page=1): url = cls.search_by_key_url.format(keyword, current_app.config['PER_PAGE'], (page-1)*current_app.config['PER_PAGE']) return HTTP.get(url)