Flask notes: 8: Fix bugs

Source: Internet
Author: User
Tags log log openid

look for bugs in the program
First look at the database with two Nickname,john,susan

log in to the project, enter it with the John User, and then modify the John username to Susan, and you will find an error





Why did you get an error? error message:integrityerror: (sqlite3. Integrityerror) column nickname is not unique [sql:u ' UPDATE user SET nickname=?, about_me=? WHERE user.id =? '] [Parameters: (U ' Susan ', U ' 12345\r\neee\r\nddd ', 1)]
because the nickname Field Unique=true, is unique and cannot be duplicated and the project is in debug mode, so the error message will be displayed on the page
Modify the mybolg/run.py and change the debug=true toFalse
From app import Appapp.run (Debug=false)



Then we'll change nickname to Susan, and we'll find the server internal error code 500

This 500 error page is handled by flask itself
Custom HTTP Error handlerDeclaring an error handler requires an adorner Crrorhandler to modify the file app/views.py
From app import app,db,lm,modelsfrom Flask import render_template,flash,redirect,url_for,session,request,gfrom. Forms Import LoginForm, Editformfrom models import userfrom flask.ext.login import Login_user,logout_user,current_user, Login_requiredfrom datetime import datetime@lm.user_loaderdef load_user (ID): Return User.query.get (int (id)) @ App.before_requestdef before_request (): G.user = Current_User if G.user.is_authenticated:g.user.last_seen=da Tetime.utcnow () Db.session.add (G.user) db.session.commit () @app. Route ('/') @app. Route ('/index ') @login_required def index (): User=g.user posts=[{' author ': {' nickname ': ' John '}, ' body ': ' Beautiful day in Por           Tland! '}, {' author ': {' nickname ': ' Susan '}, ' body ': ' The Avengers movie is so cool! '} ] Return render_template ("index.html", title= "Home", User=user, Posts=posts) @app. Route ('/login ', methods = [' G ET ', ' POST ']) def login (): If G.user is not None and g.user.is_authenticated:return Redirect (url_for (' index ')) Form = LoginForm () if Form.validate_on_submit () : If models. User.query.filter_by (Nickname=form.openid.data). First (): User = User.query.filter_by (nickname=form.openid.data) . first_or_404 () login_user (user) return redirect (Url_for (' index ')) Else:return re Nder_template (' login.html ', title = ' Sign in ', error= ' [NO] ', form = form) return Render_template (' Login.html ', title = ' Sign in ', form = form) @app. Route ('/logout ') @login_requireddef logout (): Logout_user () return redirect (Url_for (' index ')) @app. Route ('/user/<nickname> ') @login_requireddef User (nickname): user=        User.query.filter_by (Nickname=nickname). First () If User==none:flash (' user ' +nickname+ ' not found! ') Return Redirect (Url_for (' index ')) posts=[{' Author ': User, ' body ': ' Test post #1!!! '}, {' Author ': User, ' body ' ': ' Test post #2 !!!'} ] Return render_template (' user.html ', User=user, posts=posts) @app. Route ('/edit ', methods=["POST", " GET "]) @login_requireddef edit (): Form=editform () if Form.validate_on_submit (): G.user.nickname=form.nickname.  Data g.user.about_me=form.about_me.data Db.session.add (g.user) Db.session.commit () Flash (' Your        Changes have been saved! ') Return Redirect (Url_for (' user ', nickname=g.user.nickname)) Else:form.nickname.data=g.user.nickname FORM.A Bout_me.data=g.user.about_me return render_template (' edit.html ', Form=form) @app. ErrorHandler (404) def Internal_    Error: Return render_template (' 404.html '), 404@app.errorhandler (+) def internal_error (Error): Db.session.rollback () return render_template (' 500.html '), 500#errorhandler adorner, handling error #session.rollback () rollback data, Errors are found to roll back the data to the state before the error



Add 404,500 Error template, new app/templates/404.html;app/templates/500.html
404.html
{% extends "base.html"%} {% block content%}



500.html
{% extends "base.html"%} {% block content%}


Because debug mode is turned off, the server needs to be restarted before it takes effect
logging to a fileModify app/__init__.py
From flask import flaskfrom flask.ext.sqlalchemy import sqlalchemyimport osfrom flask.ext.login import loginmanagerapp= Flask (__name__) app.config.from_object ("config") db=sqlalchemy (APP) Lm=loginmanager () Lm.init_app (APP) Lm.login_ view= ' login ' if not app.debug:    import logging from    logging.handlers import Rotatingfilehandler    file_ Handler = Rotatingfilehandler (' Tmp/microblog.log ', ' a ', 1 * 1024*1024, Ten)    File_handler.setformatter (logging. Formatter ('% (asctime) s% (levelname) s:% (message) s [in% (pathname) s:% (Lineno) d] '))    app.logger.setLevel (logging. INFO)    file_handler.setlevel (logging.info)    App.logger.addHandler (File_handler)    app.logger.info (' Microblog startup ') from app import Views,models


#判断不是debug模式下执行#Logging.handlers.RotatingFileHandler (' Log save path and filename ', ' write mode [a= append] ', limit file size, save file count)
#RotatingFileHandler (' Tmp/microblog.log ', ' a ', 1 * 1024*1024, 10) means to write the log in append mode to ' Tmp/microblog.log ', limit the size of 1M, limit the number of 10 , when the Microblog.log log file more than 1M, will appear microblog.log.1, this also full will appear microblog.log.2, until 10, after the Microblog.log will be covered off, has maintained only 10 log files
#setFormatter () is formatting#logging. Formatter () is a formatted% (Levelno) S: Print the value of the log level% (levelname) S: Print log level name% (pathname) s: Prints the path of the currently executing program, which is actually sys.argv[0]% (filename) s: Prints the current name of the executing program% (funcName) s: Print the current function of the log% (Lineno) d: Print the current line number of the log% (asctime) s: Time to print logs% (thread) d: Print thread ID% (threadname) s: Print thread name% (process) d: Print process ID% (message) s: Print log information
#setLevel () setting levelDEBUG: Detailed information, usually appearing only on diagnostic issuesINFO: Make sure everything works as expectedWARNING: A sign that some unexpected things have happened, or indicate some problems in the near future (for example. Low disk space "). The software will work as expected. ERROR: A more serious problem, the software does not perform some functionsCRITICAL: A serious error that indicates that the program itself may not continue to run
#addHandler () seems to be adding handlers
#logger. info () may be a print log, record a file, but the string in the parameter is not recorded in the file
Fix bugs The following is a bug I wrote myself, unlike the original tutorial (I didn't see the original)Modify app/views.py
From app import app,db,lm,modelsfrom Flask import render_template,flash,redirect,url_for,session,request,gfrom. Forms Import LoginForm, Editformfrom models import userfrom flask.ext.login import Login_user,logout_user,current_user, Login_requiredfrom datetime import datetime@lm.user_loaderdef load_user (ID): Return User.query.get (int (id)) @ App.before_requestdef before_request (): G.user = Current_User if G.user.is_authenticated:g.user.last_seen=da Tetime.utcnow () Db.session.add (G.user) db.session.commit () @app. Route ('/') @app. Route ('/index ') @login_required def index (): User=g.user posts=[{' author ': {' nickname ': ' John '}, ' body ': ' Beautiful day in Por           Tland! '}, {' author ': {' nickname ': ' Susan '}, ' body ': ' The Avengers movie is so cool! '} ] Return render_template ("index.html", title= "Home", User=user, Posts=posts) @app. Route ('/login ', methods = [' G ET ', ' POST ']) def login (): If G.user is not None and g.user.is_authenticated:return Redirect (url_for (' index ')) Form = LoginForm () if Form.validate_on_submit () : If models. User.query.filter_by (Nickname=form.openid.data). First (): User = User.query.filter_by (nickname=form.openid.data) . first_or_404 () login_user (user) return redirect (Url_for (' index ')) Else:return re Nder_template (' login.html ', title = ' Sign in ', error= ' [NO] ', form = form) return Render_template (' Login.html ', title = ' Sign in ', form = form) @app. Route ('/logout ') @login_requireddef logout (): Logout_user () return redirect (Url_for (' index ')) @app. Route ('/user/<nickname> ') @login_requireddef User (nickname): user=        User.query.filter_by (Nickname=nickname). First () If User==none:flash (' user ' +nickname+ ' not found! ') Return Redirect (Url_for (' index ')) posts=[{' Author ': User, ' body ': ' Test post #1!!! '}, {' Author ': User, ' body ' ': ' Test post #2 !!!'} ] Return render_template (' user.html ', User=user, posts=posts) @app. Route ('/edit ', methods=["POST", " GET "]) @login_requireddef edit (): Form=editform () if Form.validate_on_submit (): If G.user.nickname!=form.nickn Ame.data and User.query.filter_by (nickname = Form.nickname.data). First ()! = None:version = 2 while True:new_nickname = Form.nickname.data + str (version) if User.query.filter_by (nickname = NE W_nickname). First () = = None:break version + = 1 Flash (' username already exist s! Recommendation: ' +form.nickname.data+str (Version) ') return redirect (Url_for (' edit ')) G.user.nickname=form. Nickname.data g.user.about_me=form.about_me.data Db.session.add (g.user) db.session.commit () FL        Ash (' Your changes has been saved! ') Return Redirect (Url_for (' user ', nickname=g.user.nickname)) ELSE:FORM.NICKNAME.DAta=g.user.nickname Form.about_me.data=g.user.about_me return render_template (' edit.html ', Form=form) @app. Errorha Ndler (404) def internal_error (Error): Return render_template (' 404.html '), 404@app.errorhandler (+) def Internal_ Error (Error): Db.session.rollback () return render_template (' 500.html '), 500



#在没有提交前全局变量中的 G.user.nickname and G.user.about_me are uploaded to the form's nickname and About_me, so the data appears in the form

#判断form表单中nickname与g中的nickname是否相同, if the same means that the user has not modified the user name#判断修改的用户名是否存在数据库中 Because each user name is unique and therefore cannot be the same#初始化一个变量version, as the user name identification, the user name in the circular database, such as john1,john2 .... Like, find out what new usernames are not.#用flash的形式告诉用户他修改的用户名已经存在, a new user name is recommended#仍然跳转到编辑页面


Unit Test FrameworkPython comes with unittest templates for testing
Import Osimport unittestfrom config import basedirfrom app import app, Dbfrom app.models import userdef jc_nickname (Nick): If User.query.filter_by (nickname = Nick). First ()! = None:version = 2 while True:new_nicknam            E = Nick + str (version) if User.query.filter_by (nickname = New_nickname). First () = = None:break Version + = 1 return new_nickname else:return nickclass TestCase (unittest. TestCase): def setUp (self): app.config[' testing ') = True app.config[' wtf_csrf_enabled '] = False AP        p.config[' sqlalchemy_database_uri ' = ' sqlite:///' + os.path.join (basedir, ' test.db ') Self.app = App.test_client () Db.create_all () def tearDown (self): Db.session.remove () Db.drop_all () def Test_make_unique_nick Name (self): U = User (nickname= ' John ', Email= ' [email protected] ') db.session.add (u) db.session.co  Mmit () Nickname=jc_nickname (' John ')      Assert nickname! = ' john ' U = User (nickname=nickname, email= ' [email protected] ') db.session.add (U ) Db.session.commit () Nickname2=jc_nickname (' John ') assert nickname2! = ' John ' assert nickname 2! = Nicknameif __name__ = = ' __main__ ': Unittest.main ()



#jc_nickname () is a custom method for detecting user name uniqueness and recommended user names#setUp () is the framework's own function, which runs before the test, which is used to connect the database and build the table#tearDown () is the framework's own function, which runs after the test and is used to empty the database#test_make_unique_nickname () custom function, the function in UnitTest must begin with test, which is used to test whether the user name can be put into storage

Flask notes: 8: Fix bugs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.