首页 > 其他 > 详细

Flask入门教程

时间:2020-03-02 18:49:47      阅读:66      评论:0      收藏:0      [点我收藏+]

Flask基础教程

1. 简介

Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

2. 基本使用

技术分享图片
from flask import Flask

app = Flask(__name__)

@app.route(/)

def hello_world():

    return Hello World!

if __name__ == __main__:

    app.run()
flask 基本使用

 

3. 配置文件

flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:

{
    DEBUG:False,
    TESTING:False,
    PROPAGATE_EXCEPTIONS: None,                          
    PRESERVE_CONTEXT_ON_EXCEPTION: None,
    SECRET_KEY: None,
    PERMANENT_SESSION_LIFETIME: timedelta(days=31),
    USE_X_SENDFILE: False,
    LOGGER_NAME: None,
    LOGGER_HANDLER_POLICY: always,
    SERVER_NAME: None,
    APPLICATION_ROOT: None,
    SESSION_COOKIE_NAME: session,
    SESSION_COOKIE_DOMAIN: None,
    SESSION_COOKIE_PATH: None,
    SESSION_COOKIE_HTTPONLY: True,
    SESSION_COOKIE_SECURE: False,
    SESSION_REFRESH_EACH_REQUEST: True,
    MAX_CONTENT_LENGTH: None,
    SEND_FILE_MAX_AGE_DEFAULT: timedelta(hours=12),
    TRAP_BAD_REQUEST_ERRORS: False,
    TRAP_HTTP_EXCEPTIONS: False,
    EXPLAIN_TEMPLATE_LOADING: False,
    PREFERRED_URL_SCHEME: http,
    JSON_AS_ASCII: True,
    JSON_SORT_KEYS: True,
    JSONIFY_PRETTYPRINT_REGULAR: True,
    JSONIFY_MIMETYPE: application/json,
    TEMPLATES_AUTO_RELOAD: None,
}

方式一:

app.config[‘DEBUG‘] = True

PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)

方式二:app.config.from_pyfile("python文件名称")

settings.py

DEBUG = True

 

app.config.from_pyfile("settings.py")
app.config.from_envvar("环境变量名称")

 

环境变量的值为python文件名称名称,内部调用from_pyfile方法

app.config.from_json("json文件名称")

 

JSON文件名称,必须是json格式,因为内部会执行json.loads

app.config.from_mapping({DEBUG:True})

 

字典格式

app.config.from_object("python类或类的路径")
app.config.from_object(pro_flask.settings.TestingConfig)

 

settings.py

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = sqlite://:memory:
    
class ProductionConfig(Config):
    DATABASE_URI = mysql://user@localhost/foo
    
class DevelopmentConfig(Config):
    DEBUG = True
    
class TestingConfig(Config):
    TESTING = True

 

PS: 从sys.path中已经存在路径开始写

PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config 为True,则就是instance_path目录

4. 路由系统

1 @app.route(/user/<username>)
3 @app.route(/post/<int:post_id>)
5 @app.route(/post/<float:post_id>)
7 @app.route(/post/<path:path>)
9 @app.route(/login, methods=[GET, POST])

 

常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:

DEFAULT_CONVERTERS = {
    default:UnicodeConverter,
    string:UnicodeConverter,
    any:AnyConverter,
    path:PathConverter,
    int:IntegerConverter,
    float:FloatConverter,
    uuid:UUIDConverter,
}

 

4.1 注册路由原理

def auth(func):
    def inner(*args, **kwargs):
        print(before)
        result = func(*args, **kwargs)
        print(after)
        return result
    return inner

@app.route(/index.html, methods=[GET, POST], endpoint=index)
@auth
def index():
    return Index 

   

def index():
    return "Index"
self.add_url_rule(rule=/index.html, endpoint="index", view_func=index, methods=["GET","POST"])

 

or

app.add_url_rule(rule=/index.html, endpoint="index", view_func=index, methods=["GET","POST"])
app.view_functions[index] = index

 

 

def auth(func):
    def inner(*args, **kwargs):
        print(before)
        result = func(*args, **kwargs)
        print(after)
        return result
    return inner

class IndexView(views.View):
    methods = [GET]
    decorators = [auth, ]
    def dispatch_request(self):
        print(Index)
        return Index!
app.add_url_rule(/index, view_func=IndexView.as_view(name=index))  # name=endpoint 

class IndexView(views.MethodView):
    methods = [GET]
    decorators = [auth, ]
    def get(self):
        return Index.GET
    def post(self):
        return Index.POST
app.add_url_rule(/index, view_func=IndexView.as_view(name=index))  # name=endpoint

@app.route和app.add_url_rule参数:

1 rule,URL规则
3 view_func, 视图函数名称
5 defaults=None, 默认值,当URL中无参数,函数需要参数时,使用 defaults={k:v}为函数提供参数
7 endpoint=None, 名称,用于反向生成URL,即: url_for(名称)
9 methods=None, 允许的请求方式,如:["GET","POST"]

strict_slashes=None,对URL最后的 / 符号是否严格要求,

如:

1 @app.route(/index,strict_slashes=False),

 

访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可

1 @app.route(/index,strict_slashes=True)

 

仅访问 http://www.xx.com/index

redirect_to=None,  重定向到指定地址

如:

1 @app.route(/index/<int:nid>, redirect_to=/home/<nid>)

 

def func(adapter, nid):
    return "/home/888"
@app.route(/index/<int:nid>, redirect_to=func)

subdomain=None, 子域名访问

from flask import Flask, views, url_for
app = Flask(import_name=__name__)
app.config[SERVER_NAME] = wupeiqi.com:5000
@app.route("/", subdomain="admin") def static_index():   """
  Flask supports static subdomains   This is available at static.your-domain.tld
  """   return "static.your-domain.tld" @app.route("/dynamic", subdomain="<username>") def username_index(username):   """
  Dynamic subdomains are also supported   Try going to user1.your-domain.tld/dynamic
  """   return username + ".your-domain.tld" if __name__ == __main__:   app.run()

 

4.1 自定制正则路由匹配

from flask import Flask, views, url_for
from werkzeug.routing import BaseConverter
app = Flask(import_name=__name__)
class RegexConverter(BaseConverter):
    """
    自定义URL匹配正则表达式
    """
    def __init__(self, map, regex):
        super(RegexConverter, self).__init__(map)
        self.regex = regex

    def to_python(self, value):
        """
        路由匹配时,匹配成功后传递给视图函数中参数的值
        :param value:
        :return:
        """
        return int(value)

    def to_url(self, value):
        """
        使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成 URL中的参数
        :param value:
        :return:
        """
        val = super(RegexConverter, self).to_url(value)
        return val
    
# 添加到flask中
app.url_map.converters[regex] = RegexConverter
@app.route(/index/<regex("\d+"):nid>)
def index(nid):
    print(url_for(index, nid=888))
    return Index
if __name__ == __main__:
    app.run()

 

5. 模板

1、模板的使用

Flask使用的是Jinja2模板,所以其语法和Django无差别

2、自定义模板方法

Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入 render_template,如:

html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>自定义函数</h1>
    {{ww()|safe}}
</body>
</html> 

run.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask,render_template
app
= Flask(__name__) def wupeiqi(): return <h1>Wupeiqi</h1>
@app.route(/login, methods=[GET, POST]) def login(): return render_template(login.html, ww=wupeiqi)
app.run()

其他:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% macro input(name, type=‘text‘, value=‘‘) %}
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
    {% endmacro %}
    {{ input(‘n1‘) }}
    {% include ‘tp.html‘ %}
    <h1>asdf{{ v.k1}}</h1>
</body>
</html>

 

6. 请求和响应

from flask import request
from flask import render_template
from flask import redirect
from flask import make_response
app = Flask(__name__)

@app.route(/login.html, methods=[GET, "POST"])
def login():
    # 请求相关信息 =====================================================================
    # request.method
    # request.args
    # request.form
    # request.values
    # request.cookies
    # request.headers
    # request.path
    # request.full_path
    # request.script_root
    # request.url
    # request.base_url
    # request.url_root
    # request.host_url
    # request.host
    # request.files
    # obj = request.files[‘the_file_name‘]
    # obj.save(‘/var/www/uploads/‘ + secure_filename(f.filename))

    # 响应相关信息 ===================================================================
    # return "字符串"
    # return render_template(‘html模板路径‘,**{})
    # return redirect(‘/index.html‘)
    # response = make_response(render_template(‘index.html‘))
    # response是flask.wrappers.Response类型
    # response.delete_cookie(‘key‘)
    # response.set_cookie(‘key‘, ‘value‘)
    # response.headers[‘X-Something‘] = ‘A value‘
    # return response
    return "内容"

if __name__ == __main__:
    app.run()

7. Session

 

除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。 它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设 置一个密钥。

1 设置:session[username] = xxx
3 删除:session.pop(username, None)

 

7.1 基本使用:

from flask import Flask, session, redirect, url_for, escape, request

app = Flask(__name__)
@app.route(/)
def index():
    if username in session:
        return Logged in as %s % escape(session[username])
    return You are not logged in

@app.route(/login, methods=[GET, POST])
def login():
    if request.method == POST:
        session[username] = request.form[username]
        return redirect(url_for(index))
    return ‘‘‘
        <form action="" method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    ‘‘‘

@app.route(/logout)
def logout():
    # remove the username from the session if it‘s there
    session.pop(username, None)
    return redirect(url_for(index))
# set the secret key.  keep this really secret:
app.secret_key = A0Zr98j/3yX R~XHH!jmN]LWX/,?RT

 

7.2 自定义Session

1 pip3 install Flask-Session

 

run.py:

from flask import Flask
from flask import session
from pro_flask.utils.session import MySessionInterface
app = Flask(__name__)
app.secret_key = A0Zr98j/3yX R~XHH!jmN]LWX/,?RT
app.session_interface = MySessionInterface()
@app.route(/login.html, methods=[GET, "POST"])
def login():
    print(session)
    session[user1] = alex
    session[user2] = alex
    del session[user2]
    return "内容"
if __name__ == __main__:
    app.run() 

session.py:

技术分享图片
import uuid
import json
import redis
from flask.sessions import SessionInterface
from flask.sessions import SessionMixin
from itsdangerous import Signer, BadSignature, want_bytes


class MySession(dict, SessionMixin):
    def __init__(self, initial=None, sid=None):
        self.sid = sid
        self.initial = initial
        super(MySession, self).__init__(initial or ())

    def __setitem__(self, key, value):
        super(MySession, self).__setitem__(key, value)

    def __getitem__(self, item):
        return super(MySession, self).__getitem__(item)

    def __delitem__(self, key):
        super(MySession, self).__delitem__(key)


class MySessionInterface(SessionInterface):
    session_class = MySession
    container = {}

    def __init__(self):
        self.redis = redis.Redis()

    def _generate_sid(self):
        return str(uuid.uuid4())

    def _get_signer(self, app):
        if not app.secret_key:
            return None
        return Signer(app.secret_key, salt=flask-session, key_derivation=hmac)

    def open_session(self, app, request):
        """
        程序刚启动时执行,需要返回一个session对象
        """
        sid = request.cookies.get(app.session_cookie_name)
        if not sid:
            sid = self._generate_sid()
            return self.session_class(sid=sid)
            signer = self._get_signer(app)
            try:
                sid_as_bytes = signer.unsign(sid)
                sid = sid_as_bytes.decode()
            except BadSignature:
                sid = self._generate_sid()
                return self.session_class(sid=sid)

    # session保存在redis中
    # val = self.redis.get(sid)
    # session保存在内存中
    val = self.container.get(sid)
    if val is not None:
        try:
            data = json.loads(val)
            return self.session_class(data, sid=sid)
        except:
            return self.session_class(sid=sid)
            return self.session_class(sid=sid)


def save_session(self, app, session, response):
    """
    程序结束前执行,可以保存session中所有的值
    如:
    保存到resit
    写入到用户cookie
    """
    domain = self.get_cookie_domain(app)
    path = self.get_cookie_path(app)
    httponly = self.get_cookie_httponly(app)
    secure = self.get_cookie_secure(app)
    expires = self.get_expiration_time(app, session)
    val = json.dumps(dict(session))
    # session保存在redis中
    # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
    # session保存在内存中
    self.container.setdefault(session.sid, val)
    session_id = self._get_signer(app).sign(want_bytes(session.sid))
    response.set_cookie(app.session_cookie_name, session_id,expires=expires, httponly=httponly,domain=domain, path=path, secure=secure)
View Code

 

7.3 第三方Session

#!/usr/bin/env python

# -*- coding:utf-8 -*-
"""
pip3 install redis
pip3 install flask-session
"""
from flask import Flask, session, redirect
from flask.ext.session import Session
app = Flask(__name__)
app.debug = True
app.secret_key = asdfasdfasd
app.config[SESSION_TYPE] = redis
from redis import Redis
app.config[SESSION_REDIS] = Redis(host=192.168.0.94,port=6379)
Session(app)
@app.route(/login)
def login():
    session[username] = alex
    return redirect(/index)

@app.route(/index)
def index():
    name = session[username]
    return name

if __name__ == __main__:

    app.run()

8. 蓝图

蓝图用于为应用提供目录划分:

8.1 小型应用程序:示例

目录结构:

技术分享图片

 

 

 

run.py:详细代码:

from pro_flask import app
if __name__ == __main__:
    app.run()

__init__.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from .views.account import account
from .views.blog import blog
from .views.user import user

app=Flask(__name__,template_folder=templates,static_folder=statics,static_url_path=/static)
app.register_blueprint(account)
app.register_blueprint(blog)
app.register_blueprint(user)

Account.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
from flask import render_template
from flask import request
account = Blueprint(account, __name__)
@account.route(/login.html, methods=[GET, "POST"])
def login():
    return render_template(login.html)

 

Blog.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
blog = Blueprint(blog, __name__)

User.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
user = Blueprint(user, __name__)

Login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户登录</h1>
<form method="POST">
    <input type="text" name="user"/>
    <input type="submit" value="提交"/>
</form>
<img src="/static/code.png">
<img src="{{ url_for(‘static‘,filename=‘code.png‘) }}">
</body>
</html>

8.2 大型应用程序:示例

目录结构:

技术分享图片

详细代码:

Run.py:

from pro_flask import app
if __name__ == __main__:
    app.run() 

__init__.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask
from .admin import admin
from .web import web
 
app = Flask(__name__)
app.debug = True
app.register_blueprint(admin, url_prefix=/admin)
app.register_blueprint(web) 

Admin/__init__.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
admin = Blueprint(admin,__name__,template_folder=templates,static_folder=static)
from . import views

Admin/views.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from . import admin
@admin.route(/index)
def index():
    return Admin.Index

Web/__init.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Blueprint
web = Blueprint(web,__name__,template_folder=templates,static_folder=static)
from . import views

Web/views.py:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from . import web
@web.route(/index)
def index():
    return Web.Index

 

8.3 其他:

蓝图URL前缀:xxx = Blueprint(‘account‘, __name__,url_prefix=‘/xxx‘)

蓝图子域名:xxx = Blueprint(‘account‘, __name__,subdomain=‘admin‘)

# 前提需要给配置SERVER_NAME: app.config[‘SERVER_NAME‘] = ‘wupeiqi.com:5000‘

# 访问时:admin.wupeiqi.com:5000/login.html

9.  Message

message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
app = Flask(__name__)
app.secret_key = some_secret
@app.route(/)
def index1():
  messages = get_flashed_messages()
  print(messages)
  return "Index1"

@app.route(/set)
def index2():
  v = request.args.get(p)
  flash(v)
  return ok

if __name__ == "__main__":
  app.run()

 

10. 中间件

from flask import Flask, flash, redirect, render_template, request
app = Flask(__name__)
app.secret_key = some_secret

@app.route(/) def index1(): return render_template(index.html) @app.route(/set) def index2(): v = request.args.get(p) flash(v) return ok class MiddleWare: def __init__(self,wsgi_app): self.wsgi_app = wsgi_app
def __call__(self, *args, **kwargs): return self.wsgi_app(*args, **kwargs) if __name__ == "__main__": app.wsgi_app = MiddleWare(app.wsgi_app) app.run(port=9999)

11. 请求扩展

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, Request, render_template
app = Flask(__name__, template_folder=templates)
app.debug = True

@app.before_first_request
def before_first_request1():
    print(before_first_request1)

@app.before_first_request
def before_first_request2():
    print(before_first_request2)

@app.before_request
def before_request1():
    Request.nnn = 123
    print(before_request1)

@app.before_request
def before_request2():
    print(before_request2)

@app.after_request
def after_request1(response):
    print(before_request1, response)
    return response

@app.after_request
def after_request2(response):
    print(before_request2, response)
    return response
 
@app.errorhandler(404)
def page_not_found(error):
    return This page does not exist, 404
 
@app.template_global()
def sb(a1, a2):
    return a1 + a2
 
@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3

@app.route(/)
def hello_world():
    return render_template(hello.html)
 
if __name__ == __main__:
    app.run()

 

调用方式:{{sb(1,2)}}  {{ 1|db(2,3)}}

12. Flask插件

12.1 WTForms

简介:

WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。

简单使用:

安装:pip install wtforms

demo1(用户登录)

app.pyfrom flask import Flask, render_template, request, redirect

from wtforms import Form
from wtforms.fields import simple
from wtforms import validators
from wtforms import widgets
app = Flask(__name__, template_folder=templates)
app.debug = True
class LoginForm(Form):
  name = simple.StringField(label=用户名,
    validators=[
      validators.DataRequired(message=用户名不能为空.),
      validators.Length(min=6, max=18, message=用户名长度必须大于%(min)d且小于%(max)d)
    ],
    widget=widgets.TextInput(),
    render_kw={class: form-control}
  )
  pwd = simple.PasswordField(
    label=密码,
    validators=[
      validators.DataRequired(message=密码不能为空.),
      validators.Length(min=8, message=用户名长度必须大于%(min)d),
      validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Z    a-z\d$@$!%*?&]{8,}",message=密码至少8个字符,至少1个大写字母,1个    小写字母,1个数字和1个特殊字符)
    ],
    widget=widgets.PasswordInput(),
    render_kw={class: form-control}
  )
@app.route(/login, methods=[GET, POST])
def login():
  if request.method == GET:
    form = LoginForm()
    return render_template(login.html, form=form)
  else:
    form = LoginForm(formdata=request.form)
    if form.validate():
      print(用户提交数据通过格式验证,提交的值为:, form.data)
    else:
      print(form.errors)
  return render_template(login.html, form=form)
if __name__ == __main__:   app.run()

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>登录</h1>
<form method="post">
<!--<input type="text" name="name">-->
<p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>
<!--<input type="password" name="pwd">-->
<p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>

demo2(用户注册):

app.py

from flask import Flask, render_template, request, redirect

from wtforms import Form

from wtforms.fields import core

from wtforms.fields import html5

from wtforms.fields import simple

from wtforms import validators

from wtforms import widgets

app = Flask(__name__, template_folder=‘templates‘)

app.debug = True

class RegisterForm(Form):

name = simple.StringField(

label=‘用户名‘,

validators=[

validators.DataRequired()

],

widget=widgets.TextInput(),

render_kw={‘class‘: ‘form-control‘},

default=‘alex‘

)

 

pwd = simple.PasswordField(

label=‘密码‘,

validators=[

validators.DataRequired(message=‘密码不能为空.‘)

],

widget=widgets.PasswordInput(),

render_kw={‘class‘: ‘form-control‘}

)

 

pwd_confirm = simple.PasswordField(

label=‘重复密码‘,

validators=[

validators.DataRequired(message=‘重复密码不能为空.‘),

validators.EqualTo(‘pwd‘, message="两次密码输入不一致")

],

widget=widgets.PasswordInput(),

render_kw={‘class‘: ‘form-control‘}

)

 

email = html5.EmailField(

label=‘邮箱‘,

validators=[

validators.DataRequired(message=‘邮箱不能为空.‘),

validators.Email(message=‘邮箱格式错误‘)

],

widget=widgets.TextInput(input_type=‘email‘),

render_kw={‘class‘: ‘form-control‘}

)

 

gender = core.RadioField(

label=‘性别‘,

choices=(

(1, ‘男‘),

(2, ‘女‘),

),

coerce=int

)

 

city = core.SelectField(

label=‘城市‘,

choices=(

(‘bj‘, ‘北京‘),

(‘sh‘, ‘上海‘),

)

)

 

hobby = core.SelectMultipleField(

label=‘爱好‘,

choices=(

(1, ‘篮球‘),

(2, ‘足球‘),

),

coerce=int

)

favor = core.SelectMultipleField(

label=‘喜好‘,

choices=(

(1, ‘篮球‘),

(2, ‘足球‘),

),

widget=widgets.ListWidget(prefix_label=False),

option_widget=widgets.CheckboxInput(),

coerce=int,

default=[1, 2]

)

def __init__(self, *args, **kwargs):

super(RegisterForm, self).__init__(*args, **kwargs)

self.favor.choices = ((1, ‘篮球‘), (2, ‘足球‘), (3, ‘羽毛球‘))

 

def validate_pwd_confirm(self, field):

"""

自定义pwd_confirm字段规则,例:与pwd字段是否一致

:param field:

:return:

"""

# 最开始初始化时,self.data中已经有所有的值

if field.data != self.data[‘pwd‘]:

# raise validators.ValidationError("密码不一致") # 继续后续验证

raise validators.StopValidation("密码不一致")  # 不再继续后续验证

 

@app.route(‘/register‘, methods=[‘GET‘, ‘POST‘])

def register():

if request.method == ‘GET‘:

form = RegisterForm(data={‘gender‘: 1})

return render_template(‘register.html‘, form=form)

else:

form = RegisterForm(formdata=request.form)

if form.validate():

print(‘用户提交数据通过格式验证,提交的值为:‘, form.data)

else:

print(form.errors)

return render_template(‘register.html‘, form=form)

if __name__ == ‘__main__‘:

app.run()

 

register.html

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

</head>

<body>

<h1>用户注册</h1>

<form method="post" novalidate style="padding:0  50px">

{% for item in form %}

<p>{{item.label}}: {{item}} {{item.errors[0] }}</p>

{% endfor %}

<input type="submit" value="提交">

</form>

</body>

</html>

 

如何实现:

源码流程:

1.解释:metaclass

2.实例:form = LoginForm

3.验证:form.validate()

 

12.2 SQLAchemy

SQLAlchemy项目基础实例

项目结构:

  

 

 __init__.py

from flask import Flask

  from flask_sqlalchemy import SQLAlchemy

  from .views.admin import admin

  from .views.shop import shop

  db = SQLAlchemy()

  from .models import  *

  def create_app():

app = Flask(__name__, template_folder=‘templates‘, static_folder=‘statics‘, static_url_path=‘/static‘)

# 导入配置文件(以类的形式导入)

app.config.from_object("settings.TsetSesstings")

# 将db注册到app中(在内部读取配置文件)      db.init_app(app)

#注册蓝图      

app.register_blueprint(admin)

app.register_blueprint(shop)

return app

 


run.py

# 程序入口from flask_app import create_app

app = create_app()

if __name__ == ‘__main__‘:

    app.run()

 

settings.py

# 这是配置文件
# 测试配置
class TsetSesstings():

    DEBUG = True

    TESTING = True

    SECRET_KEY = "djcishcnieodkscj9codscojsojcd0ojc"

    ‘‘‘

    数据库连接配置

    SQLALCHEMY_DATABASE_URI‘, ‘sqlite:///:memory:‘

    SQLALCHEMY_BINDS‘, None

    SQLALCHEMY_NATIVE_UNICODE‘, None

    SQLALCHEMY_ECHO‘, False

    SQLALCHEMY_RECORD_QUERIES‘, None

    SQLALCHEMY_POOL_SIZE‘, None

    SQLALCHEMY_POOL_TIMEOUT‘, None

    SQLALCHEMY_POOL_RECYCLE‘, None

    SQLALCHEMY_MAX_OVERFLOW‘, None

    SQLALCHEMY_COMMIT_ON_TEARDOWN‘, False

    ‘‘‘

    SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:密码@localhost:3306/数据库名‘

    SQLALCHEMY_POOL_SIZE = 5

    SQLALCHEMY_POOL_TIMEOUT = 30

    SQLALCHEMY_POOL_RECYCLE = -1

    # 追踪对象的修改并且发送信号

    SQLALCHEMY_TRACK_MODIFICATIONS = False

# 正式配置

class FormalSettings():

    DEBUG = False

    TESTING = False

    SECRET_KEY = "xfsec@admin!2019(shuijizifuchuan)"

    #数据库连接

  SQLALCHEMY_DATABASE_URI = ‘mysql+pymysql://root:密码@localhost:3306/数据库名‘

   SQLALCHEMY_POOL_SIZE = 5
   SQLALCHEMY_POOL_TIMEOUT = 30
   SQLALCHEMY_POOL_RECYCLE = -1
   # 追踪对象的修改并且发送信号
   SQLALCHEMY_TRACK_MODIFICATIONS = False

 

models.py

from . import db

class Users1(db.Model):

    __tablename__ = "users"

    id  = db.Column(db.Integer,primary_key=True)

    username = db.Column(db.String(50),nullable=False,unique=True)

    email = db.Column(db.String(150), nullable=False, unique=True)

    def __repr__(self):

        return "<Users %r>" %self.username

 

crcate_tables.py 

# 这是一个创建数据库表的脚本

from flask_app import db

from flask_app import create_app

app = create_app()

with app.app_context():

db.create_all()

 

admin.py 

from flask import Blueprint

from flask import render_template

from flask import request

# 创建app应用

# url_prefix : 路由拼接

# template_folder : 模板路径

admin= Blueprint(‘admin‘, __name__, url_prefix=‘/admin‘, template_folder=‘templates‘)

 

# 每次请求进来时的操作
@admin.before_request
def process_request(*args, **kwargs):
     ‘‘‘
    判断用户是否登陆
     ‘‘‘
     if request.path == "/admin_dingding_xfsec/login":
        print("登录页面不需要登陆!!!")
        return None
   else:
        print("后台每次请求进来时都会执行这个函数")

#每次请求结束时的操作(必须加return 否则会报错!!!)
@admin.after_request
def process_response(response):
     print("后台每次请求结束后都会执行这个函数")
     return response

 

@admin.route(‘/login‘, methods=[‘GET‘, "POST"])
def login():
     if request.method == "GET":
return "前端登录页面!!!"
else:
         pass

@admin.route(‘/index‘, methods=[‘GET‘, "POST"])
def index():
if request.method == "GET":
return "前端首页!!!"
else:
pass

 

shop.py

from flask import Blueprintfrom flask import render_templatefrom flask import request

‘‘‘

前端管理函数处理

使用蓝图

创建蓝图实例

创建路由

函数处理‘‘‘

shop = Blueprint(‘shop‘, __name__, template_folder=‘templates‘)

# 每次请求进来时的操作

@shop.before_requestdef process_request(*args, **kwargs):

    print("前端每次请求进来时都会执行这个函数")

 

# 每次请求结束时的操作(必须加return 否则会报错!!!)

@shop.after_requestdef process_response(response):

    print("前端每次请求结束后都会执行这个函数")

    return response

 

@shop.route(‘/login‘, methods=[‘GET‘, "POST"])def login():

    if request.method == "GET":

        return "前端登录页面!!!"

    else:

        pass

 

 

@shop.route(‘/index‘, methods=[‘GET‘, "POST"])def index():

    if request.method == "GET":

        return "前端首页!!!"

    else:

        pass

 

等...    http://flask.pocoo.org/extensions/

 

Flask入门教程

原文:https://www.cnblogs.com/xingxingnbsp/p/12397155.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!