Flash project creation and configuration

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)

Tags: Python Back-end Flask

Posted on Mon, 08 Nov 2021 23:43:39 -0500 by alexinjamestown