人工智能学习笔记:Flask的重点细节、重点与快速入门(长期更新)

一、虚拟环境

二、Flask视图基础和URL

  1. Content-type:可以指定服务器与客户端之间传输数据类型和数据的编码类型

    Mime-type:不能指定传输的数据编码类型(Content-type>Mine-type)

  2. pycharm2017.1开启debug模式的方法:

    1. app.run(debug=True)
    2. app.debug=True
    3. app.config.update(DEBUG=True)
    4. 创建文件config.py ==> 写入DEBUG=True ==>import config ==> app.config.from_object(config)
    5. 创建文件config.py ==> 写入DEBUG=True ==>import config ==> app.config.from_pyfile(config.py)
    6. pycharm2018以上在configuration中修改FLASK_DEBUG打勾,Additional options: --host=0.0.0.0 --port=8000
  3. 第一种传递参数方式(路径):

    @app.route('/article/<id>/')
    def article(id):
        print(id)
        return "你传入的id为:%s"%id
    
  4. 参数类型:string int float path uuid

    @app.route('/<any(user,blog):module>/<int:id>/')
    def list1(module, id):  
        if module=='blog':
            return "博客详情:%s"%id
        else:
            return "用户详情:%s"%id
    
  5. 第二中参数传递方式

    1. get请求:request.args.get(‘uname’)
    2. post请求:request.form.get(‘uname’)
    from flask import request
    @app.route('/list7/',methods=['GET','POST'])
    def list2():
        if request.method == 'GET':
            uname = request.args.get('uname')
            pwd = request.args.get('pwd')
            return render_template('login.html')
        elif request.method == 'POST':
            uname = request.form.get('uname')
            pwd = request.form['pwd']
            return "接收到的参数为:%s %s" %(uname,pwd)
    
  6. 使用url_for() 函授构建url, 接收两个以上的参数,第一个参数为”[函数名]“,接受对应url规则的命名函数,(//)如果出现其他参数,会添加到url的后面作为查询参数(?key=value)

  7. 自定义URL转化器

    1. regex= 用来按对应规则捕获参数
    2. to_python(self,value) 用来操作URL中参数返回value(URL到函数中参数时生效)
    3. to_url(self,value)在调用url_for()传入参数时生效(url_for()到URL时生效)
    from werkzeug.routing import BaseConverter
    class TelephoneConveter(BaseConverter):
        regex = r"1[345789]\d{9}"
    
    app.url_map.converters['tel'] = TelephoneConveter
    
  8. return redirect()重定向

三、Flask之Jinja2模板

  1. 修改tempate的默认路径

    app = Flask(__name__,template_folder='d:/demo')
    
  2. render_remplate()传递多个参数, content是一个字典

    return render_template('/news/news_list.html',**content) #使用传参技巧
    return render_template('/news/news_list.html',c = content) #不使用传参技巧
    
  3. 过滤器基本语法 {{variable|过滤器名字}}

    <p>位置的绝对值为:{{position|abs}}</p>
    
  4. 常见过滤器:

    • abs(value):返回一个数值的绝对值。 例如:-1|abs。

    • default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。name|default(‘xiaotuo’)——如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。

    • escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。例如:content|escape或content|e。

    • first(value):返回一个序列的第一个元素。names|first。

    • format(value,*arags,**kwargs):格式化字符串。例如以下代码:

      {{ “%s” - “%s”|format(‘Hello?’,“Foo!”) }}将输出:Helloo? - Foo!

    • last(value):返回一个序列的最后一个元素。示例:names|last。

    • length(value):返回一个序列或者字典的长度。示例:names|length。

    • join(value,d=’+’):将一个序列用d这个参数的值拼接成字符串。

    • safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。

    • int(value):将值转换为int类型。

    • float(value):将值转换为float类型。

    • lower(value):将字符串转换为小写。

    • upper(value):将字符串转换为小写。

    • replace(value,old,new): 替换将old替换为new的字符串。

    • truncate(value,length=255,killwords=False):截取length长度的字符串。

    • striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。

    • trim:截取字符串前面和后面的空白字符。

    • string(value):将变量转换成字符串。

    • wordcount(s):计算一个长字符串中单词的个数。

    • reverse() 反向遍历

  5. ‘autoescape’ jinja标签可以对里面的代码块开启或关闭自动转义

    {% autoescape off %}
    	...代码块
    {% endautoescape %}
    
  6. 自定义过滤器:

    @app.template_filter('cut')
    def cut(value):
        value = value.replace("abc","***")
        return value
    
  7. 将模板设置为自动加载模式(可以加载templates中的html文件):

    app.config['TEMPLATES_AUTO_RELOAD']=True
    
  8. 条件判断语句if:

    {% if age>=18 %}
    	<p>已经成年</p>
    {% elif age>10 %}
    	<p>未成年</p>
    {% else %}
    	<p>你太小了</p>
    {% endif %}
    
  9. 循环语句for:(没有continue 和 break 语句)

    {% for user in users %}
            <li>{{ user }}</li>
        {% else %}
            <li>没有任何用户</li>    #user为空执行此处
        {% endfor %}
    
  10. Jinja中的for循环还包含以下变量,可以用来获取当前的遍历状态:

    • | loop.index | 当前迭代的索引(从1开始) |

    • | loop.index0 | 当前迭代的索引(从0开始) |

    • | loop.first | 是否是第一次迭代,返回True或False |

    • | loop.last | 是否是最后一次迭代,返回True或False |

    • | loop.length | 序列的长度 |

  11. 定义宏

    {% macro inp(uname,type="text",value="") %}
            <input type="{{ type }}" name="{{ uname }}" value="{{ value }}">
        {% endmacro %}
    
  12. 宏的导入两种方式:

    {% from "macros/macros.html" import input as inp %}  #以templates为根路径
    #[with context]在定义宏的页面,使用引用宏的页面的参数
    {% import "macros/macros.html" as macros  with context %}
    
  13. 导入include:复制粘贴的形式到页面

    {% include "commons/top.html" %}
    
  14. set定义的变量在后面都可以使用(全局),with只能在语句块中使用(局部)

  15. 加载静态文件:

    <link type="text/css" rel="stylesheet" href="{{url_for("static",filename='css/index.css')}}" >
    
  16. 模板继承语法

    base.html:
    	...<title>
    		{% block block_title %}
    			xyz
    		{% endblock %}
    	</title>...
    index.html:
    	{% extends "parents/base.html" %}
    	...<title>
    		{% block block_title %}
    			{{super()}}  #xyz
    			要覆盖的内容
    			{{self.block_title()}} # 引用其他模块 
    		{% endblock %}
    	</title>...
    

四、Flask视图高级

  1. add_url_rule(rule,endpoint=None,view_func=None)用来添加url与视图函数的映射,如果写了endpoint值,则在使用url_for()时要使用endpoint值(app.route()底层就是借助此方法实现)

    app.add_url_rule("/list/",endpoint='li',view_func=my_list)
    
  2. 创建注册类视图:

    from flask import views
    class ListView(views.View):
        def dispatch_request(self):
            return "这是List列表"
    app.add_url_rule('/list/',view_func=ListView.as_view('my_list'))
    
    with app.test_request_context():
        print(url_for('my_list'))
    
  3. 重写get()、post()方法(不推荐get、post方法相互调用)

  4. 在视图函数中使用自定义装饰器,必须放在app.route()下面

  5. 在类视图中使用装饰器,需要重写类视图的一个类属性decorators,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。

    def login_requierd(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            username = request.args.get("username")
            if username and username =='momo':
                 return func(*args,**kwargs)
            else:
                return  '请先登录'
        return wrapper
        
     class  ProfileView(views.View):
        decorators = [login_requierd]
        def dispatch_request(self):
            return '这是个人中心界面'
    
  6. 蓝图:

    blueprints/users.py:
    	from flask import Blueprint
    	users_bp = Blueprint("users",__name__,url_prefix='/users',	
    		template_folder='users_page')#仍然优先从templates中查找
    	@users_bp.route("/aaa/")
    	def aaa():
        	return "我是aaa啊"
        	
    app.py:
    	from blueprints.users import users_bp
    	app = Flask(__name__)
    	app.register_blueprint(users_bp)
    
  7. 如果在加载静态文件的时候,指定的蓝图的名字,比如news.static,那么就会到这个蓝图指定的static_folder下查找静态文件。

    news_bp = Blueprint('news',__name__,url_prefix='/news',
    	template_folder='news_page',static_folder='news_page_static')
    html:
    <link rel="stylesheet" href="{{ url_for('news.static',filename='news_list.css') }}">
    
  8. url_for()反转蓝图

    url_for("users.aaa")
    
  9. 子域名:

    cms_bp= Blueprint('cms',__name__,subdomain='cms')
    app.config['SERVER_NAME']='momo.com:5000'   
    

五、Flask高级

  1. Response.set_cookie()创建cookie,Response.delete_cookie()删除cookie

  2. 设置session

    import os
    from datetime import timedelta
    app = Flask(__name__)
    app.config['SECRET_KEY'] = os.urandom(24)
    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=2)
    @app.route('/setsession')
    def setsession():
        session['uname'] = 'momo'
        session.permanent = True
        return 'hello'
    
  3. 手动推入应用上下文:

    #方式一
    app_context_obj = app.app_context()
    app_context_obj.push()
    print(current_app.name)
    #方式二
    with app.app_context():
    	print(current_app.name)
    
  4. 手动推入请求上下文:

    with app.test_request_context():
        #手动推入一个请求上下文到请求上下文栈中
        #如果当前app应用上下文栈中没有app应用上下文,那么会首先推入一个app应用上下文到栈中
        print(url_for('my_list'))
    
  5. 钩子函数

    • @app.before_first_request 项目处理第一次请求前执行此函数

    • @app.before_request 每次请求前执行

    • @app.context_processor 上下文处理器(在render_template()前执行)。必须返回一个字典,字典中的值所有模板都可以使用

    • @app.errorhandler(500) 接收状态码,自定义返回这种状态码的响应的处理方法。

      ​ abort(400) : 跳转到400错误

      @app.errorhandler(500)
      def server_error(error):
          return render_template('500.html'),500
      
  6. 自定义信号

    from blinker import Namespace
    aSpace = Namespace()                         #创建信号
    mysignal = aSpace.signal("信号名字")
    def func(sender):
        print(sender)
    mysignal.connect(func)                       #监听信号
    mysignal.send()                              #发送信号
    
  7. request.remote_addr 获取对方ip地址

  8. 内置信号

    • template_rendered:模版渲染完成后的信号。

      def funcc(sender,template, context):
          print(sender)		#发送者
          print(template)		#跳转到模板的名称
          print(context)		#跳转到模板页面带过去的参数
      template_rendered.connect(funcc)
      
    • before_render_template:模版渲染之前的信号。

    • request_started:请求开始之前,在到达视图函数之前发送信号。

    • request_finished:请求结束时,在响应发送给客户端之前发送信号。

    • request_tearing_down:请求对象被销毁时发送的信号,即使在请求过程中发生异常也会发送信号。

    • got_request_exception:在请求过程中抛出异常时发送信号,异常本身会通过exception传递到订阅(监听)的函数中。一般可以监听这个信号,来记录网站异常信息。

    • appcontext_tearing_down:应用上下文被销毁时发送的信号。

    • appcontext_pushed:应用上下文被推入到栈上时发送的信号。

    • appcontext_popped:应用上下文被推出栈时发送的信号。

    • message_flashed:调用了Flask的flash方法时发送的信号。

  9. WTForms:pip install flask-wtf

  10. WTForms表单验证基本使用:

    from wtforms import Form,StringField
    from wtforms.validators import Length,EqualTo
    class RegisterForm(Form):
        uname = StringField(validators=[Length(min=2,max=15,message="用户名必须在2-15长度之间")])
        pwd = StringField(validators=[Length(min=6,max=12)])
        pwd2 = StringField(validators=[Length(min=6,max=12),EqualTo('pwd')])
    
    
    @app.route('/register/',methods=['GET','POST'])
    def register():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            form = RegisterForm(request.form)
            if form.validate():
                return "验证通过"
            else:
                print(form.errors)
                return "验证不通过"
    
  11. 常用验证器:

    • Length:字符串长度限制,有min和max两个值进行限制。

    • EqualTo:验证数据是否和另外一个字段相等,常用的就是密码和确认密码两个字段是否相等。

    • Email:验证上传的数据是否为邮箱数据格式 如:223333@qq.com。

    • InputRequired:验证该项数据为必填项,即要求该项非空。

    • NumberRange:数值的区间,有min和max两个值限制,如果处在这两个数字之间则满足。IntegerField

    • Regexp:定义正则表达式进行验证,如验证手机号码。

    • URL:必须是URL的形式 如http://www.bjsxt.com。

    • UUID:验证数据是UUID类型。

  12. 自定义验证器(方法命名规则:‘validate_’+验证属性名

        code = StringField(validators=[Length(min=4,max=4)])
        def validate_code(self,field):
            if field.data != str(session.get('code')):
                raise ValidationError(message="验证码不通过")
    
  13. 上传文件并验证

    from werkzeug.utils import secure_filename
    from werkzeug.datastructures import  CombinedMultiDict
    from flask_wtf.file import FileRequired,FileAllowed
    class UploadForm(Form):
        pichead = FileField(validators=[FileRequired(),FileAllowed(['jpg','png','gif'])])
        desc = StringField(validators=[InputRequired()])
        
    UPLOAD_PATH = os.path.join(os.path.dirname(__file__),'images')
    
    @app.route('/upload/',methods=['GET','POST'])
    def upload():
        if request.method == 'GET':
            return render_template('upload.html')
        else:
            form = UploadForm(CombinedMultiDict([request.form,request.files]))
            if form.validate():
                # desc = request.form.get("desc")
                # pichead = request.files.get("pichead")
                desc = form.desc.data
                pichead = form.pichead.data
                filename = secure_filename(pichead.filename)
                pichead.save(os.path.join(UPLOAD_PATH,filename))
                return '文件上传成功'
            else:
                print(form.errors)
                return "文件上传失败"
    
  14. 访问服务器已经上传成功的文件

    from flask import send_from_directory
    @app.route('/images/<filename>/')
    def get_image(filename):
        return send_from_directory(UPLOAD_PATH,filename)
    
  15. Flask_RESTfull基本使用

    from flask_restful import Resource,Api
    api = Api(app)
    class LoginView(Resource):
        def get(self):
            return {"flag":"no"}
        def post(self):
            return {"flag":'yes'}
    api.add_resource(LoginView,"/login/",'/login2/',endpoint=...)
    with app.test_request_context():
    	print(url_for('loginview'))  #若没有指定endpoint将使用视图的小写作为endpoint。
    
  16. 参数验证:

    • default:默认值,如果这个参数没有值,那么将使用这个参数指定的默认值。
    • required:是否必须。默认为False,如果设置为True,那么这个参数就必须提交上来。
    • type:这个参数的数据类型,如果指定,那么将使用指定的数据类型来强制转换提交上来的值。
    • choices:固定选项。提交上来的值只有满足这个选项中的值才符合验证通过,否则验证不通过。
    • help:错误信息。如果验证失败后,将会使用这个参数指定的值作为错误信息。
    • trim:是否要去掉前后的空格。
      • 其中的type,
        可以使用python自带的一些数据类型(如str或者int),
        也可以使用flask_restful.inputs下的一些特定的数据类型来强制转换。
        比如一些常用的:
        url:会判断这个参数的值是否是一个url,如果不是,那么就会抛出异常。
        regex:正则表达式。
        date:将这个字符串转换为datetime.date数据类型。如果转换不成功,则会抛出一个异常。
    from flask_restful import Api,Resource,reqparse,inputs
    class RegisterView(Resource):
        def post(self):
            parser = reqparse.RequestParser()
            parser.add_argument('uname',type=str,help='用户名验证错误!',
            	required=True,trim=True)
            args = parser.parse_args()
            print(args)
            return {"tips":"注册成功"}
    
  17. 标准化参数返回:

    from flask_restful import Resource,Api,fields,marshal_with
    class New():
        def __init__(self,title,content):
            self.title = news_title
            self.content = content
            self.signature=None
    
    class LoginView(Resource):
        resourse_field = {
            'title':fields.String(attribute='news_title'),
            'content':fields.String
            'signature':fields.String(default='此人很懒,什么也没写')
        }
        @marshal_with(resourse_field)
        def get(self):
            new = New("titleee","contenttt")
            return new
    
  18. __str__和__repr__的区别,在列表中repr仍然打印,而str只打印地址值
    
  19. 标准参数强化 复杂参数

    class NewsView2(Resource):
        resource_fields={
            'id':fields.Integer,
            'title': fields.String,
            'content': fields.String,
            #如在一个字段下面又是一个字典,那么可以使用fields.Nested({...})
            'author': fields.Nested({
                'id': fields.Integer,
                'uname': fields.String,
                'age':fields.Integer
            }),
            #如要在一个字段中放置一个列表,那么可以使用fields.List(fields.Nested({...}))
            'tags': fields.List(fields.Nested({
                'id': fields.Integer,
                'name': fields.String
            }))
        }
    
  20. 渲染模板:

    class ListView(Resource):
        def get(self):
            return render_template('index.html')  #不渲染返回字符串
    @api.representation('text/html')
    def output_html(data,code,headers):
        if isinstance(data,str):
            # 在representation装饰的函数中,必须返回一个Response对象
            # resp = make_response(data)
            resp =Response(data)
            return resp
        else:
            return Response(json.dumps(data),mimetype='application/json'
    

六、Flask数据库

  1. 创建 连接数据库:

    from sqlalchemy import create_engine
    #准备连接数据库基本信息
    HOSTNAME = '127.0.0.1'
    PORT = '3306'
    DATABASE = 'test01'
    USERNAME = 'root'
    PASSWORD = 'root'
    DB_URI ="mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8"
    	.format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE)
    #创建数据库引擎
    engine = create_engine(DB_URI)
    #创建连接
    conn = engine.connect()
    
  2. 基于ORM模型映射到数据库中

    from sqlalchemy import create_engine, Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    Base = declarative_base(engine)
    class Persion(Base):
        __tablename__='person'
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)
        country = Column(String(50))
    Base.metadata.drop_all()
    Base.metadata.create_all()
    
  3. SQLAlchemy对数据的添加:

    from sqlalchemy.orm import sessionmaker
    session = sessionmaker(engine)()
    p1 = Persion(name='lulu',age=20,country='china')
    p2 = Persion(name='tantan',age=18,country='china')
    session.add_all([p1,p2])
    session.commit()
    
  4. SQLAlchemy对数据的查找更新删除:

    ps = session.query(Person).all()
    ps = session.query(Person).filter_by(name='tantan').all()
    ps = session.query(Person).filter(Person.name=='lulu').all()
    ps = session.query(Person).get(1)
    ps = session.query(Person).first()
    
    ps.name = 'haha'
    ps.delete(ps)
    session.commit()
    
  5. SQLAlchemy的常用数据类型:

    1. Integer:整形,映射到数据库中是int类型。

    2. Float:浮点类型,映射到数据库中是float类型。他占据的32位。

    3. Double:双精度浮点类型,映射到数据库中是double类型,占据64位 (SQLALCHEMY中没有)。

    4. String:可变字符类型,映射到数据库中是varchar类型.

    5. Boolean:布尔类型,映射到数据库中的是tinyint类型。

    6. DECIMAL:定点类型。是专门为了解决浮点类型精度丢失的问题的。在存储钱相关的字段的时候建议大家都使用这个数据类型。并且这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位。

    7. Enum:枚举类型。指定某个字段只能是枚举中指定的几个值,不能为其他值。在ORM模型中,使用Enum来作为枚举,示例代码如下:

      class News(Base):
      __tablename__ = 'news'
          tag = Column(Enum("python",'flask','django'))
      
      在Python3中,已经内置了enum这个枚举的模块,我们也可以使用这个模块去定义相关的字段。示例代码如下:
      class TagEnum(enum.Enum):
          python = "python"
      flask = "flask"
          django = "django"
      
      class News(Base):
          __tablename__ = 'news'
      id = Column(Integer,primary_key=True,autoincrement=True)
          tag = Column(Enum(TagEnum))
        
      news = News(tag=TagEnum.flask)
      
    8. Date:存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用datetime.date来指定。

    9. DateTime:存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用datetime.datetime来指定。

    10. Time:存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用datetime.time来至此那个。示例代码如下:

      class News(Base):
      __tablename__ = 'news'
          create_time = Column(Time)
      news = News(create_time=time(hour=11,minute=11,second=11))
      
    11. Text:存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型。

    12. LONGTEXT:长文本类型,映射到数据库中是longtext类型。

    from  sqlalchemy  import  create_engine,Column,Integer,String,Float,Enum,Boolean,DECIMAL,Text,Date,DateTime,Time
    from  sqlalchemy.ext.declarative  import declarative_base
    from  sqlalchemy.dialects.mysql  import LONGTEXT
    from  sqlalchemy.orm  import  sessionmaker
    
    import  enum
    from  datetime import date
    from  datetime import datetime
    from  datetime import time
    #准备数据库的一堆信息    ip  port    user  pwd   数据库的名称   按要求组织格式
    HOSTNAME = '127.0.0.1'
    PORT = '3306'
    DATABASE = 'first_sqlalchemy'
    USERNAME = 'root'
    PASSWORD = 'root'
    
    #dialect+driver://username:password@host:port/database?charset=utf8
    #按照上述的格式来 组织数据库信息
    DB_URI ="mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".\
        format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE)
    
    #创建数据库引擎
    engine = create_engine(DB_URI)
    #创建会话对象
    session =  sessionmaker(engine)()
    #定义一个枚举类
    class   TagEnum(enum.Enum):
         python="PYHTON2"
         flask="FLASK2"
         django ="DJANGO"
    
    
    #创建一个ORM模型     说明基于sqlalchemy  映射到mysql数据库的常用字段类型有哪些?
    Base = declarative_base(engine)
    class News(Base):
        __tablename__='news'
        id = Column(Integer,primary_key=True,autoincrement=True)
        price1 = Column(Float)  #存储数据时存在精度丢失问题
        price2 = Column(DECIMAL(10,4))
        title = Column(String(50))
        is_delete =Column(Boolean)
        tag1 =Column(Enum('PYTHON','FLASK','DJANGO'))  #枚举常规写法
        tag2 =Column(Enum(TagEnum)) #枚举另一种写法
        create_time1=Column(Date)
        create_time2=Column(DateTime)
        create_time3=Column(Time)
        content1 =Column(Text)
        content2 =Column(LONGTEXT)
    
    # Base.metadata.drop_all()
    
    # Base.metadata.create_all()
    
    #新增数据到表news中
    
    # a1 = News(price1=1000.0078,price2=1000.0078,title='测试数据',is_delete=True,
    tag1="PYTHON",tag2=TagEnum.flask,create_time1=date(2018,12,12),
    create_time2=datetime(2019,2,20,12,12,30),create_time3=time(hour=11,minute=12,second=13),content1="hello",content2 ="hello   hi   nihao")
    
    a1 = News(price1=1000.0078,price2=1000.0078,title='测试数据',
    is_delete=False,tag1="PYTHON",tag2=TagEnum.python,       create_time1=date(2018,12,12),create_time2=datetime(2019,2,20,12,12,30),
    create_time3=time(hour=11,minute=12,second=13),content1="hello",content2 ="hello   hi   nihao")
    session.add(a1)
    session.commit()
    
  6. SQLAlchemy的常用参数:

    1. primary_key:True设置某个字段为主键。
    2. autoincrement:True设置这个字段为自动增长的。
    3. default:设置某个字段的默认值。在发表时间这些字段上面经常用。
    4. nullable:指定某个字段是否为空。默认值是True,就是可以为空。
    5. unique:指定某个字段的值是否唯一。默认是False。
    6. onupdate:在数据更新的时候会调用这个参数指定的值或者函数。在第一次插入这条数据的时候,不会用onupdate的值,只会使用default的值。常用于是update_time字段(每次更新数据的时候都要更新该字段值)。
    7. name:指定ORM模型中某个属性映射到表中的字段名。如果不指定,那么会使用这个属性的名字来作为字段名。如果指定了,就会使用指定的这个值作为表字段名。这个参数也可以当作位置参数,在第1个参数来指定。
      title = Column(String(50),name=‘title’,nullable=False)
      title = Column(‘my_title’,String(50),nullable=False
  7. query函数可传递的参数:

    1. 模型名。指定查找这个模型中所有的属性(对应查询表为全表查询)。
    2. 模型中的属性。可以指定只查找某个模型的其中几个属性。
    3. 聚合函数。
      • func.count:统计行的数量。
      • func.avg:求平均值。
      • func.max:求最大值。
      • func.min:求最小值。
      • func.sum:求和。
        func上,其实没有任何聚合函数。但是因为他底层做了一些魔术,只要mysql中有的聚合函数,都可以通过func调用。
  8. 创建外键:

    uid = Colum(integer,ForeignKey('user.id',ondelete='RESTRICT'))
    
  9. 外键查询:

    class User(Base):
        __tablename__ = 'user'
        id = Column(Integer,primary_key=True,autoincrement=True)
        uname = Column(String(50),nullable=False)
    
        # newss=relationship("News")  #这种写法不是最优的,通常会把它通过反向声明的方式写在“多”的那一方
        def __repr__(self):
            return "<User(uname:%s)>" % self.uname
    
    class News(Base):
        __tablename__ = 'news'
        id = Column(Integer,primary_key=True,autoincrement=True)
        title = Column(String(50),nullable=False)
        content = Column(Text,nullable=False)
        #外键
        uid = Column(Integer,ForeignKey("user.id"))
    
        #正向author = relationship("User")
        #正向 和 反向在一起 表明两个模型之间的关系
        author = relationship("User",backref="newss")
    
        def __repr__(self):
            return "<News(title:%s,content=%s)>" % (self.title,self.content)
    
    
    # Base.metadata.drop_all()
    # Base.metadata.create_all()
    
    #需求1:查询 第一篇新闻的 作者是谁
    # news= session.query(News).first()
    # print(news)
    # print(news.uid) #1
    # user = session.query(User).get(news.uid)
    # print(user.uname)
    
    #上述的需求  能够被实现  但是太麻烦,引入relationship进行查询优化
    # news = session.query(News).first()
    # print(news.author)
    # print(news.author.uname)
    
    #需求2:查询xx作者的所有文章
    user = session.query(User).first()
    print(user.newss)
    
  10. 文档。。。。。。。。。。。。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这个需求做不l

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值