返回顶部

基础flask开发时遇到的问题总结

flask开发小Demo

涉及的知识点:

蓝图, 配置文件, flask-session, flask-sqlalchemy, flask-script, flask-migrate....

遇到的小坑。。。

1.应该把引用的蓝图对象放到create_app中:

import os

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_session import Session

from exts.auth import Auth

db = SQLAlchemy()
auth = Auth()


def create_app():
    app = Flask(__name__)
    app.config.from_object('settings.DevelopmentConfig')
    app._static_folder = os.path.abspath("static/")
    from flaskDemo3.views.account import ac
    from flaskDemo3.views.home import home
    from flaskDemo3.views.host import host
    app.register_blueprint(ac)
    app.register_blueprint(home)
    app.register_blueprint(host)

    Session(app)

    db.init_app(app)
    auth.init_app(app)
    return app

2.在使用context_processor给全局模板传变量的时候,应该返回一个字典,并且模板中使用key来调用变量

def init_app(self, app):
app.auth_manage = self
self.app = app
app.before_request(self.check_login)
app.context_processor(self.context_processor)

def
context_processor(self): user_info = session.get('user_info') return dict(current_user=user_info) # 模板中使用

3. 通过flask-sqlalchemy来插入和更新数据时,有两种方式,第一种通过原生sql,第二种通过sqlalchremy的add方法:

############插入数据#############
#
第一种:对于字段很多的对象,这种方式比较方便。 db.session.execute('insert into users(name, pwd, age) values(:user, :pwd, :age)', form.data) db.session.commit() db.session.remove() # 第二种: user = form.data['user'] pwd = form.data['pwd'] obj = models.Users(name=user, pwd=pwd) db.session.add(obj) db.session.commit() db.session.remove()

################更新数据##########
title = form.data.get('title')
ip = form.data.get('ip')
depart = form.data.get('depart')

db.session.query(models.Hosts).filter(models.Hosts.id == pk).update({models.Hosts.title:title, models.Hosts.ip:ip,
models.Hosts.depart:depart})
 

4. 用wtforms定义字段的时候,不要在某个字段类,比如SelectField中,进行数据库操作,容易报错:

No application found. Either work inside a view function or push an application context. 

有两种解决办法:

第一种:
    最下面通过init来赋值
    def __init__(self, *args, **kwargs):
        super(HostForm, self).__init__(*args, **kwargs)
        self.depart.choices = db.session.query(models.Depart.id, models.Depart.title).all()

第二种:
  在视图中赋值
    form = MenuForm()
    if request.method == "GET":
  
    form.depart.choices = [(v.id, v.title) for v in db.session.query(models.Depart).all()]

5. 反向查询的应用注意:

from sqlalchemy import Column, String, Integer,ForeignKey
from sqlalchemy.orm import relationship

# model.py:
class Hosts(db.Model):

    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(32), nullable=False)
    ip = Column(String(32),nullable=False)
    depart = Column(Integer,ForeignKey('depart.id'))
    dps = relationship('Depart', backref='hosts')

class Depart(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(32), nullable=False)

#############查询所有主机的名称和部门名称######## host_list
= db.session.query(models.Hosts).all() for item in host_list: print(item.title, item.dps.title) #############查询部门id为2的所有主机名称和部门名称####### dep_obj = db.session.query(models.Depart).filter(models.Depart.id==2).first() host_list = dep_obj.hosts for item in host_list: print(item.title, item.dps.title)

6. 关于模板中,静态文件的路径问题:

静态文件路径常见几种写法:

 

 第一种: 注意前面的反斜杠一定加上。

<link rel="shortcut icon" href="/static/imgs/luffy-study-logo.png">

第二种:
<img class="logo" src="{{ url_for('static', filename='imgs/logo.svg') }}">

7. 通过wtforms做更新操作,带上原来的数据到模板。

wtforms做更操作时,带上原有的数据:

if request.method == 'GET':
form = HostForm()
form.title.data = host_obj.title
form.ip.data = host_obj.ip
form.depart.data = host_obj.depart

return render_template('change.html', form=form)

 

 

8. 关于浏览器访问服务器图片

@ac.route('/media/<username>')
def get_img(username):
    user_obj = db.session.query(models.UserInfo).filter(models.UserInfo.name==username).first()
    avatar = user_obj.avatar
    filepath = 'media/imgs/%s' % (avatar)  # 注意路径的拼接
    # print(filepath)

    return send_file(filepath)

# user_obj.avatar存的是图片的名称default.png。
# 前端根据模板字符串就可以获取:
<p><img src="/media/{{ current_user['user'].name }}" style="width: 56px; height: 56px;"></p>

 

9. 通过sqlAlchemy查询操作完后:

 

可以执行db.session.remove(),但是不需要commit()。不然会报错!

记住,更新数据完后,要commit() 

 

10.Parent instance <User at 0x2ceb5aaa160> is not bound to a Session;lazy load operation of attribute 'dep' cannot proceed (Background on this error at: http://sqlalche.me/e/13/bhk3)

 这种情况主要是: session 已经被提交,导致操作的 model 对象已经不在当前 session 中了。

举例:

current_app.auth_manager.login({'id': uid, 'user': user_obj})

往session中存了对象后,又取出,通过外键去查询某些字段的时候,就会报这个错。

# 解决办法:
登录成功后,可以往session中存一个该用户的唯一值,比如用户名,id, token等,然后再需要获取对象某些字段值的地方:
    user_dict = session.get('user_info')
    username = user_dict['user']
    user_obj = db.session.query(models.User).filter(models.User.name==username).first()

    print(user_obj.name, user_obj.dep.title)

 

 

----------------------未完待续

 

posted @ 2020-10-06 20:50  muguangrui  阅读(183)  评论(0)    收藏  举报