zoukankan      html  css  js  c++  java
  • flask1 + jinja2 day88

    人工智能方向 - 智能玩具

    -1 所学内容:

    1.flask(前后端交互的接口)(返回api(json))

    2.MongoDB NoSQL(自由度高,(没什么限制),操作就难)4版本(多了个事务)+3.4

    3.人工智能 A.I. 应用技术 Not 算法和机器学习

    4.webSocket 全双工通讯 IM即时通讯

    5.Mui(布局,布局一个 ) + HTML5Plus(打开硬件有封装) App (工作了,就是一个小儿科,这些框架,质的飞跃)

    6.智能玩具 + 机器学习

    0 Django 和 Flask 优劣势

    Django 15天

    ​ 优势:组件全 - admin - Model ORM - Forms
    ​ 教科书式(其他框架和他像)

    ​ 劣势:加载的组件是全部的组件 - 占用资源较高
    ​ 重型框架

    Flask 3 天

    ​ 优势:轻如鸿毛 扩展性极强 三方组件全

    ​ 劣势:什么组件都没有
    ​ 三方组件全 - 版本兼容问题 导致不稳定
    ​ 线程的支持(不如dj)

    1 flask 初识

    1.1 flask 安装+启动

    安装

    新建pure python项目
    -new environment 选择 Virtualenv
    --选择interpreter
    ---选择make available to all projects

    启动

    在大目录下,新建一个py文件

    from flask import Flask		#导入Flask以及别的
    app=Flask(__name__)			#Flask第1个参数 模块名 
    app.run()	 #默认访问http://127.0.0.1:5000/ 端口启动也可以指定别的端口
    比如:#  app.run('0.0.0.0',9527)
    

    Flask 源码:

    def __init__(
            self,
            import_name,
    

    返回错误 503 可以连接,但是没有返回视图

    1.2 模板的书写

    from flask import Flask,render_template	 #返回模板
    app=Flask(__name__)			
    @app.route('/')	  # route() 装饰器 url 触发--> 函数
    def home():
        # return 1					#不能返回整型
        return 'hello world'		#可字符,字典,列表
    @app.route('/index')		
    def index():					
        return render_template('index.html')	#来渲染模板。
    app.run()			
    

    方法:

    1 写一个templates
    把index.html 放了里面 然后飘黄

    2 make dir template dir 选择jinja2 (webpy ,django,等) (Django封装了(要不也可以使用jiaja2了) jinja2最好 )

    Flask 会在 templates 文件夹里寻找模板, 之后就可以向django一样使用模板了,自动补全
    所以,如果你的应用是个模块,这个文件夹应该与模块同级;如果它是一个包,那么这个文件夹作为包的子目录:

    情况 1: 模块:

    /application.py
    /templates
        /hello.html
    

    情况 2: 包:

    /application
        /__init__.py
        /templates
            /hello.html
    

    1.3 flask1.1之前使用jsonify

    jsonify 模块

    from flask import Flask,render_template,jsonify
    @app.route('/json')
    def my_jsonify():
        # return jsonify({'a':1})	#字典转成json字符串
        return {'k':1}				#1.1后支持直接传字典
    
    return jsonify(username=g.user.username,...
    --------》
    This will send a JSON response like this to the browser::
      {
                "username": "admin",...          
    

    flask 中的返回特殊封装 2个

    1 jsonify 转换标准JSON格式

    ​ 响应头中加入 Content-type:application/json
    ​ app/json 自动的将 转换成object?字典?

    ​ flask1.1下 直接返回字典了,可以不用使用jsonify (向下兼容了) (flask之前的的必须使用jsonify,作为一个开发两年的mn)

    2 send_file 发送文件

    alt + 回车(补全import)
    打开并返回文件内容,
    自动识别文件类型,
    响应头中加入了 Content-Type

    前端 : 只和request有关系
    所有response都是后端处理的
    
    text  image   audio/mpeg(MP3)  video/mp4(两次请求,http请求数据是有限制的,流媒体,节省服务器资源) 		my_file	my_file	
    
    所有浏览器无法识别的东西: 都以下载的格式返回	
    比如zip格式的	Content-Type: application/x-zip-compressed
    
    爬虫的时候: 采集视频难,一段一段,中间还得带验证码
    

    当我传MP3MP4格式的时候,发现MP3格式的图标是? 而MP4的格式是文本一样(但是可以传说明没问题)

    send_file代码如下:(文件都在主目录下)

    @app.route('/my_file')
    def my_file():
        # return send_file('1.png')
        # return send_file('app01.py')
        # return send_file('1.mp3')
        # return send_file('1.mp4')
        # return send_file('1.jpg')
        return send_file('1.zip')
    

    if name == 'main':

    作用:执行的时候才走,被别的调用的时候不走了

    from flask import Flask,render_template
    app = Flask(__name__)
    
    @app.route('/login')
    def login():
        return render_template('login.html')
    
    if __name__ == '__main__':  # 只有调用的时候才执行  别的文件引入时候不执行
        app.run()
    

    2 . request

    <h1>login</h1>
    <form action="" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="password" name="pwd">
        <input type="submit" value="登录">
    

    405 : 请求方式不被允许

    127.0.0.1 - - [10/Jul/2019 10:32:53] "GET /login HTTP/1.1" 200 -
    127.0.0.1 - - [10/Jul/2019 10:33:03] "POST /login HTTP/1.1" 405 -
    

    解决:

    @app.route('/login',methods=['POST','GET'])
    

    route允许post和get方法

    request是全局的(公共对象),第一个用户进来了,第二个用户也都能用 那就不支持多进程了,有解决方法

    request.form 获取FormData的数据 - Form表单

    request = LocalProxy(partial(_lookup_req_object, "request"))
    
    if request.method == 'GET':     #请求方式
    	return render_template('login.html')
    if request.method == 'POST':
    	print(request.form)
    	print(request.form.get('username'))
    	print(request.form.to_dict())
    	return '200 OK'
    
    ImmutableMultiDict([('username', 'asdfas'), ('pwd', 'adfasd')])			#多重字典    看到dict用get
    
    2.2 request参数
    request.headers      #请求头中的数据
    
    request.url #访问路径    http://127.0.0.1:5000/login
    request.path#路由地址   /login
    
    综合获取
    request.values  #获取URL中的参数 也可以获取FormData中的数CombinedMultiDict([ImmutableMultiDict([('id', '1'), ('ids', '2')]), ImmutableMultiDict([('username', '123'), ('pwd', '456')])])
    request.values.get('id') # 
    
    request.args.to_dict()   #获取url参数{'id': '1', 'ids': '2'}
    request.args['id'])     # key value key没有值会报错,get比较好	 比如: KeyError: 'id'
    request.args.to_dict()['id']
    
    request.environ    #获取请求原始信息 #{'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http',  .........}
    
    request.base_url     #获取url头,不包含参数 							 #http://127.0.0.1:5000/login
    request.json        #请求头con-type:app/json 数据序列化  #None
    request.data       #请求头中contype 不包含Form or data #b''
          
          
    request.headers      #Host: 127.0.0.1:5000      
    

    request.value的坑

    由于都是ImmutableMultiDict([('id', '1'),
    如果前端提交name写了id  那么.to_dict() 就会被覆盖
    先写的dataform后写的url,url覆盖
    
    2. #指定目录保存

    默认保存到主目录(项目)下

    my_file = request.files.get('my_file')
    my_file.save('save.jpg')
    fp = os.path.join('templates',my_file.filename)  #
    my_file.save(fp)  #指定目录保存到templates下
    
    

    区分form和from的方法

    Form 表单 - FormData
    f orm - 表单  
    from 
    
    2.# 自动重启

    django自带的

    # app.config['DEBUG'] = True
    app.debug = True #避免重启
    
    按ctrl + s  重启 
    切换也重启 
    
    2.# url? 传参
    <http://127.0.0.1:5000/login?id=1>
    

    这样访问 ?传输参数 不会对地址路由造成影响 是传参了

    3 模板传参的写法

    3.1 py 视图
    STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'}
    STUDENT_LIST = [
        {'name': 'Old', 'age': 38, 'gender': '中'},...
    STUDENT_DICT = {
        1: {'name': 'Old', 'age': 38, 'gender': '中'},..
      
      def 
      return render_template('index1.html', stu_info = STUDENT, stu_list = STUDENT_LIST, stu_dict = STUDENT_DICT,absum =ab)
    
    3.2 模板文件写法
    (1)stu_info
    <table border="1px">
        <tr>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
    
      <tr>
            <td>{{ stu_info.name }}</td>
           <td>{{ stu_info.get('age') }}</td>
    		 <td>{{ stu_info['gender'] }}</td>
    		 #三种方式都可以获得字典的  但是key的慎用
    
    (2)stu_list
    {% for foo in stu_list %}	#(改性别)
       <td>{% if foo.gender!='男' and foo.gender!='女' %}
                    女
                     {% else %}
                    {{ foo.gender }}
    
    (3)stu_dict(两种方式 dict或者items()(不要忘了括号))
    {% for id in stu_dict %}
        <tr>
            <td>{{ id }}</td>
            <td>{{ stu_dict[id].name }}</td>
            <td>{{ stu_dict.get(id).get('age') }}</td>
     
    
    {% for id,s in stu_dict.items() %}
        <tr>
            <td>{{ id }}</td>
            <td>{{ s.name }}</td>
            <td>{{ s.get('age') }}</td>
    

    id 和 s

    {#    {{ id  }}   {#1 {'name': 'Old', 'age': 38, 'gender': '中'} 2 {'name': 'Boy', 'age': 73, 'gender': '男'} 3 {'name': 'EDU', 'age': 84, 'gender': '女'}#} #}
    {#    {{ s }}#}
    
    (4)所有的模板都用到这个函数(传函数)
    @app.template_global()      #全局的
    def ab(a,b):
        return a+b
    

    通常做一个模块,到引入就行了,都引入

    return render_template('index1.html',absum =ab)#传到模板   #不用absum的  全局的
    

    模板使用

    center>{{ absum }}</center>
    <center>{{ ab(2,2) }}</center>
    
    #<function ab at 0x0000000003873488>
    #4
    
    (5)宏函数(什么用?)生成一个标签?
    {% macro my_input(na,ty)%}
        <input type="{{ ty }}" name="{{ na }}">
    {% endmacro %}
    
    {{ my_input('uname','text')}}
    

    传给模板一个标签

    my_in = Markup("<input type= 'text',name='uname'>")
    return render_template('index1.html',m=my_in)
    
    {{m}}		#使用
    
    3.2 jinja2

    {{}} 引用 or 执行

    {%%} 逻辑语法 if for else

    今天上课都是因为一个,逗号困住,所以不得往下面的,可惜,细节

    4 session

    登录页面提交方式

    <h1>login</h1>
    {#<form action="/login?id=1&ids=2" method="post" enctype="multipart/form-data">#}
    														#url却是post方式的提交
    <form action="" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="password" name="pwd">
    {#    <input type="file" name="my_file">#}				#提交文件
        <input type="submit" value="登录">
    
    

    session和request同级的,不和Django一样,request.django

    request = LocalProxy(partial(_lookup_req_object, "request"))
    session = LocalProxy(partial(_lookup_req_object, "session"))			#基本一样
    
    登录+加入session(默认31天)
    app.secret_key = '*Ud8fadjfadkjfaidjf' 	#验证码
    @app.route('/login',methods=['POST',"GET"])
    def login():
        if request.method == 'GET':
            return render_template('login.html')
    
        uname = request.form.get('username')
        pwd = request.form.get('pwd')
    
        if uname == '123' and pwd == '123':
            session['username'] = uname
    
    session登录
    @app.route('/detail')
    def detail():
        if session.get('username'):
            return render_template('index.html')
        else:
            return redirect('/login')
    
    

    session存到哪了?

    Flask中的Session 不是三方组件 //Flask-Session

    1. 内置的

    from flask import session

    session['username'] = uname #加入session

    RuntimeError
    The session is unavailable because no secret key was set.  Set the secret_key on the application to something unique and secret.
    解决:   app.secret_key = '*Ud8fadjfadkjfaidjf'  ####密钥的写法不是app.session,而是app
    
    

    session 交由客户端保管

    反序列化机制

    当客户端发起请求 -request 带上cookie - cookie中有session的加密字符串 -flask 收到session加密字符串 - 通过 secret_key 解密session的加密字符串 获得 {username : 123}

    app.permanent_session_lifetime = 15 (默认是秒)

    都可以改 这些内容 (别再源码里改,提出来改)进入源码: session-->global session app.py里的内容

    "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
    

    程序里改:

    app.permanent_session_lifetime = 15
    

    查看在前端application-->Cookies--> 代替了cookie, network点击login里没有改

    app.session_cookie_name = "I am Not Session"		
    
    app.testing = True
    

    序列化机制

    开启session - session['username'] = uname

    创建一个字典 {username:123} 接下来 通过secret_key(密钥安全) + 时间戳 + 签名 加密 形成

    eyJ1c2VybmFtZSI6IjEyMyJ9.XSVovw.g6ZxiiEw_0EhRHF--oTG9Ac-ZF8 session的加密字符串
    签名.时间戳.数据

        if uname == '123' and pwd == '123':
            session['username'] = uname
    
        if uname == '123' and pwd == '123':
            session['username'] = uname
            session['username1'] = uname
            session['username2'] = uname 
    

    .eJyrViotTi3KS8xNVbJSMjQyVtKBCxhiiBhhiBhDRWoBGaYU8w.XSXASw.cExXNorpTmERznwqRl9mdO4Tu7Y 写了多个session,session就多了很多 因为{username:123,username1:123,} 有公共机制所以说: 不会太长了

    if uname == '123' and pwd == '123':
        session['dasgas'] = '打分'
        session['ada'] =  '网页'		
    

    .eJyrViotTi3KS8xNVbJSiik1NTK0iCk1SzFIUtKByxjiljLCLWWMLlULACpUIRM.XSXBYw.uZrsOt2eoTJX4pJPoxQk4wSxjJY(多了,因为2个汉字6个)

    不能线上开debug,会暴露密钥,在前端页面显示错误的时候,可能就会暴露,相对安全不是绝对的安全了

    5 全局变量global

    错了好多次了

    a = 0
    
    @app.route('/detail')
    def detail():
        global a
        if session['username']:
            a += 1
            print(a)
    

    作业:

    1 用装饰器装饰一个登录函数

    ​ 返回request(双重装饰器)

    2 每一个视图函数都加上装饰器

    能写三遍的不写两遍,背诵默写,哪不会的

    工具:

    不要太依赖,如果没有pycharm怎么办
    记事本怎么写,能不能写 (今天学的可不可以写)
    之后可能是各种工具

    之后花钱买个 视频 看看破解版的  专业的(两三块钱)
    不要更新		(把算法替换掉)
    

    pycharm 是java写的, java的算法 , 乱码是算法的值,就连上了

    规划:技术之上

    技术:是掉接口的码农?还是
    架构:更偏向技术
    懂技术的产品还可以

    工作经验

    会,必须要全会,才算掌握一个语言 --龙

    面试

    看面试官 眉心 就可以把人看紧张了
    吹了27k,本来15k。。。压力也大
    15 16 K的程序员 都是应用层次的 用过什么
    25k的左右的是接触过什么架构 什么项目

    吹得话: ai开放能力,找一个,学或者了解()
    人工智能 有标签 ,提上简历,有一个算法,招标签

    龙交的nlp,还真会点 18k,把自己吹太牛了,不敢去(很能吹的南方人 能吹offer多7个)

    遇到特别不屑的,直接走,转身走(不要回头)

    sanic

    学习稍微难些
    最新的框架,python最快的 (先天写的东西都比他快的很多)(世界上没有最好的语言,自己用的就是最好的,没有最好的程序员,自己) python数据计算非常快

    错误1 多加了个逗号字典变元祖

    STUDENT = {'name': 'Old', 'age': 38, 'gender': '中'} ,
    

    stu_info = STUDENT 时 , stu_info.name 等都没有值,是空的 ,而stu_info 有值 等于:
    ({'name': 'Old', 'age': 38, 'gender': '中'},)

    以后不要犯这种错误

    多加了个,成了元祖类型了(其实提示了tuple not get ,但是不看提示,看了也不懂把)

    自己写程序出的错

    错误2 AttributeError

    1 AttributeError: read only property

    request.method = ['POST','GET']		--->request.methods = ['POST','GET']
    

    2 jinja2.exceptions.TemplateNotFound
    jinja2.exceptions.TemplateNotFound: login.html #---> 扔到主目录下,把文件

    3 Method Not Allowed (405 403)
    The method is not allowed for the requested URL.

       request.methods = ['POST','GET']    #这个写法不对,没法分配POST方法
    

    ​ -->@app.route('/login',methods=['POST',"GET"])#直接写上面

    错误3 记错命令 还一直坚持尝试

    ctrl + enter 不是快速导入的命令
    alt + enter 才是快速导入模块的命令

    快捷键1

    再加个命令 ctrl+shift+i 是前端的检查快捷键

  • 相关阅读:
    c语言求最大公约数和最小公倍数(转)
    git 提交去除每次输账号密码
    phpstorm使用zen coding 快速编辑补全html/css代码
    YII2.0使用ActiveForm表单(转)
    php面向对象之trait
    php操作redis(转)
    模块
    列表生成式 与生成器表达式
    三元表达式,递归,内置函数
    面向过程的编程思想
  • 原文地址:https://www.cnblogs.com/Doner/p/11163116.html
Copyright © 2011-2022 走看看