人工智能学习笔记:Flask的重点细节、重点与快速入门(长期更新)-程序员宅基地

技术标签: python  django  机器学习  深度学习  人工智能  神经网络  

一、虚拟环境

二、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:验证上传的数据是否为邮箱数据格式 如:[email protected]

    • 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. 文档。。。。。。。。。。。。。。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mingzme/article/details/107250226

智能推荐

C#连接OPC C#上位机链接PLC程序源码 1.该程序是通讯方式是CSharp通过OPC方式连接PLC_c#opc通信-程序员宅基地

文章浏览阅读565次。本文主要介绍如何使用C#通过OPC方式连接PLC,并提供了相应的程序和学习资料,以便读者学习和使用。OPC服务器是一种软件,可以将PLC的数据转换为标准的OPC格式,允许其他软件通过标准接口读取或控制PLC的数据。此外,本文还提供了一些学习资料,包括OPC和PLC的基础知识,C#编程语言的教程和实例代码。这些资料可以帮助读者更好地理解和应用本文介绍的程序。1.该程序是通讯方式是CSharp通过OPC方式连接PLC,用这种方式连PLC不用考虑什么种类PLC,只要OPC服务器里有的PLC都可以连。_c#opc通信

Hyper-V内的虚拟机复制粘贴_win10 hyper-v ubuntu18.04 文件拷贝-程序员宅基地

文章浏览阅读1.6w次,点赞3次,收藏10次。实践环境物理机:Windows10教育版,操作系统版本 17763.914虚拟机:Ubuntu18.04.3桌面版在Hyper-V中的刚安装好Ubuntu虚拟机之后,会发现鼠标滑动很不顺畅,也不能向虚拟机中拖拽文件或者复制内容。在VMware中,可以通过安装VMware tools来使物理机和虚拟机之间达到更好的交互。在Hyper-V中,也有这样的工具。这款工具可以完成更好的鼠标交互,我的..._win10 hyper-v ubuntu18.04 文件拷贝

java静态变量初始化多线程,持续更新中_类初始化一个静态属性 为线程池-程序员宅基地

文章浏览阅读156次。前言互联网时代,瞬息万变。一个小小的走错,就有可能落后于别人。我们没办法去预测任何行业、任何职业未来十年会怎么样,因为未来谁都不能确定。只能说只要有互联网存在,程序员依然是个高薪热门行业。只要跟随着时代的脚步,学习新的知识。程序员是不可能会消失的,或者说不可能会没钱赚的。我们经常可以听到很多人说,程序员是一个吃青春饭的行当。因为大多数人认为这是一个需要高强度脑力劳动的工种,而30岁、40岁,甚至50岁的程序员身体机能逐渐弱化,家庭琐事缠身,已经不能再进行这样高强度的工作了。那么,这样的说法是对的么?_类初始化一个静态属性 为线程池

idea 配置maven,其实不用单独下载Maven的。以及设置新项目配置,省略每次创建新项目都要配置一次Maven_安装idea后是不是不需要安装maven了?-程序员宅基地

文章浏览阅读1w次,点赞13次,收藏43次。说来也是惭愧,一直以来,在装环境的时候都会从官网下载Maven。然后再在idea里配置Maven。以为从官网下载的Maven是必须的步骤,直到今天才得知,idea有捆绑的 Maven 我们只需要搞一个配置文件就行了无需再官网下载Maven包以后再在新电脑装环境的时候,只需要下载idea ,网上找一个Maven的配置文件 放到 默认的 包下面就可以了!也省得每次创建项目都要重新配一次Maven了。如果不想每次新建项目都要重新配置Maven,一种方法就是使用默认的配置,另一种方法就是配置 .._安装idea后是不是不需要安装maven了?

奶爸奶妈必看给宝宝摄影大全-程序员宅基地

文章浏览阅读45次。家是我们一生中最重要的地方,小时候,我们在这里哭、在这里笑、在这里学习走路,在这里有我们最真实的时光,用相机把它记下吧。  很多家庭在拍摄孩子时有一个看法,认为儿童摄影团购必须是在风景秀丽的户外,即便是室内那也是像大酒店一样...

构建Docker镜像指南,含实战案例_rocker/r-base镜像-程序员宅基地

文章浏览阅读429次。Dockerfile介绍Dockerfile是构建镜像的指令文件,由一组指令组成,文件中每条指令对应linux中一条命令,在执行构建Docker镜像时,将读取Dockerfile中的指令,根据指令来操作生成指定Docker镜像。Dockerfile结构:主要由基础镜像信息、维护者信息、镜像操作指令、容器启动时执行指令。每行支持一条指令,每条指令可以携带多个参数。注释可以使用#开头。指令说明FROM 镜像 : 指定新的镜像所基于的镜像MAINTAINER 名字 : 说明新镜像的维护(制作)人,留下_rocker/r-base镜像

随便推点

毕设基于微信小程序的小区管理系统的设计ssm毕业设计_ssm基于微信小程序的公寓生活管理系统-程序员宅基地

文章浏览阅读223次。该系统将提供便捷的信息发布、物业报修、社区互动等功能,为小区居民提供更加便利、高效的服务。引言: 随着城市化进程的加速,小区管理成为一个日益重要的任务。因此,设计一个基于微信小程序的小区管理系统成为了一项具有挑战性和重要性的毕设课题。本文将介绍该小区管理系统的设计思路和功能,以期为小区提供更便捷、高效的管理手段。四、总结与展望: 通过本次毕设项目,我们实现了一个基于微信小程序的小区管理系统,为小区居民提供了更加便捷、高效的服务。通过该系统的设计与实现,能够提高小区管理水平,提供更好的居住环境和服务。_ssm基于微信小程序的公寓生活管理系统

如何正确的使用Ubuntu以及安装常用的渗透工具集.-程序员宅基地

文章浏览阅读635次。文章来源i春秋入坑Ubuntu半年多了记得一开始学的时候基本一星期重装三四次=-= 尴尬了 觉得自己差不多可以的时候 就吧Windows10干掉了 c盘装Ubuntu 专心学习. 这里主要来说一下使用Ubuntu的正确姿势Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的开源GNU/Linux操作系统,Ubuntu 是基于DebianGNU/Linux,支..._ubuntu安装攻击工具包

JNI参数传递引用_jni引用byte[]-程序员宅基地

文章浏览阅读335次。需求:C++中将BYTE型数组传递给Java中,考虑到内存释放问题,未采用通过返回值进行数据传递。public class demoClass{public native boolean getData(byte[] tempData);}JNIEXPORT jboolean JNICALL Java_com_core_getData(JNIEnv *env, jobject thisObj, jbyteArray tempData){ //resultsize为s..._jni引用byte[]

三维重建工具——pclpy教程之点云分割_pclpy.pcl.pointcloud.pointxyzi转为numpy-程序员宅基地

文章浏览阅读2.1k次,点赞5次,收藏30次。本教程代码开源:GitHub 欢迎star文章目录一、平面模型分割1. 代码2. 说明3. 运行二、圆柱模型分割1. 代码2. 说明3. 运行三、欧几里得聚类提取1. 代码2. 说明3. 运行四、区域生长分割1. 代码2. 说明3. 运行五、基于最小切割的分割1. 代码2. 说明3. 运行六、使用 ProgressiveMorphologicalFilter 分割地面1. 代码2. 说明3. 运行一、平面模型分割在本教程中,我们将学习如何对一组点进行简单的平面分割,即找到支持平面模型的点云中的所有._pclpy.pcl.pointcloud.pointxyzi转为numpy

以NFS启动方式构建arm-linux仿真运行环境-程序员宅基地

文章浏览阅读141次。一 其实在 skyeye 上移植 arm-linux 并非难事,网上也有不少资料, 只是大都遗漏细节, 以致细微之处卡壳,所以本文力求详实清析, 希望能对大家有点用处。本文旨在将 arm-linux 在 skyeye 上搭建起来,并在 arm-linux 上能成功 mount NFS 为目标, 最终我们能在 arm-linux 里运行我们自己的应用程序. 二 安装 Sky..._nfs启动 arm

攻防世界 Pwn 进阶 第二页_pwn snprintf-程序员宅基地

文章浏览阅读598次,点赞2次,收藏5次。00为了形成一个体系,想将前面学过的一些东西都拉来放在一起总结总结,方便学习,方便记忆。攻防世界 Pwn 新手攻防世界 Pwn 进阶 第一页01 4-ReeHY-main-100超详细的wp1超详细的wp203 format2栈迁移的两种作用之一:栈溢出太小,进行栈迁移从而能够写入更多shellcode,进行更多操作。栈迁移一篇搞定有个陌生的函数。C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 _pwn snprintf

推荐文章

热门文章

相关标签