blog.miguelgrinberg.com
ãã²ã«ã»ã°ãªã³ããŒã°
<<<å 次>>>
ãã®èšäºã¯ãMiguel Greenbergã«ããæç§æžã®æ°çã®ç¬¬5éšã®ç¿»èš³ã§ãããèè
ã®åºçç©ã¯2018幎5æã«å®äºããäºå®ã§ãã以åã®ç¿»èš³ã¯ããã®é¢é£æ§ãé·ã倱ããŸããã
ããã¯ãFlask Mega-Tutorialã·ãªãŒãºã®ç¬¬5å·ã§ããããŠãŒã¶ãŒãã°ã€ã³ãµãã·ã¹ãã ã®äœææ¹æ³ã説æããŸãã
åèãŸã§ã«ã以äžã¯ãã®ã·ãªãŒãºã®èšäºã®ãªã¹ãã§ãã
泚1ïŒãã®ã³ãŒã¹ã®å€ãããŒãžã§ã³ããæ¢ãã®å Žåã¯ããã¡ããã芧ãã ãã ã
泚2ïŒçªç¶ããã®ããã°ã®ç§ã®ïŒãã²ã«ïŒã®ä»äºãæ¯æããŠå£°ãäžãããå ŽåããŸãã¯åã«èšäºã1é±éåŸ
ã€å¿èããªãå Žåãç§ïŒãã²ã«ã°ãªãŒã³ããŒã°ïŒã¯ãã®ã¬ã€ãã®å®å
šçã«ããã±ãŒãžåãããé»åæžç±ãŸãã¯ãããªãæäŸããŸãã 詳现ã«ã€ããŠã¯ã learn.miguelgrinberg.comãã芧ãã ãã ã
第3ç« ã§ã¯ ããŠãŒã¶ãŒãã°ã€ã³ãã©ãŒã ã®äœææ¹æ³ãåŠã³ã 第4ç« ã§ã¯ãããŒã¿ããŒã¹ã®æäœæ¹æ³ãåŠã³ãŸããã ãã®ç« ã§ã¯ãããã2ã€ã®ç« ã®ãããã¯ãçµã¿åãããŠç°¡åãªãŠãŒã¶ãŒãã°ã€ã³ã·ã¹ãã ãäœæããæ¹æ³ãåŠç¿ããŸãã
ãã®ç« ã®GitHubãªã³ã¯ïŒ Browse ã Zip ã Diff ã
ãã¹ã¯ãŒãããã·ã¥
ãŠãŒã¶ãŒã¢ãã«ã®ç¬¬4ç« ã§ã¯ ã password_hash
ãã£ãŒã«ããå²ãåœãŠãããŸãããããŸã 䜿çšãããŠããŸããã ãã®ãã£ãŒã«ãã®ç®çã¯ããŠãŒã¶ãŒã®ãã¹ã¯ãŒãããã·ã¥ãä¿åããããšã§ããããã¯ãç»é²ããã»ã¹äžã«ãŠãŒã¶ãŒãå
¥åãããã¹ã¯ãŒãã®æ€èšŒã«äœ¿çšãããŸãã ãã¹ã¯ãŒãããã·ã¥ã¯ã»ãã¥ãªãã£ã®å°é家ã«ä»»ããã¹ãè€éãªãããã¯ã§ãããã¢ããªã±ãŒã·ã§ã³ããåŒã³åºããããã«ãã®ããžãã¯ããã¹ãŠå®è£
ãã䜿ããããã©ã€ãã©ãªãããã€ããããŸãã
ãã¹ã¯ãŒãããã·ã¥ãå®è£
ããããã±ãŒãžã®1ã€ã«WerkzeugããããŸããããã¯ãFlaskã®ã€ã³ã¹ããŒã«æã«pipã®åºåã§ç¢ºèªã§ããå¯èœæ§ããããŸãã ããã¯äŸåé¢ä¿ã§ãããããWerkzeugã¯ä»®æ³ç°å¢ã«æ¢ã«ã€ã³ã¹ããŒã«ãããŠããŸãã 次ã®Pythonã·ã§ã«ã»ãã·ã§ã³ã¯ããã¹ã¯ãŒããããã·ã¥ããæ¹æ³ã瀺ããŠããŸãã
>>> from werkzeug.security import generate_password_hash >>> hash = generate_password_hash('foobar') >>> hash 'pbkdf2:sha256:50000$vT9fkZM8$04dfa35c6476acf7e788a1b5b3c35e217c78dc04539d295f011f01f18cd2175f'
ãã®äŸã§ã¯ãfoobarãã¹ã¯ãŒãã¯ãéæŒç®ãè¡ããªãäžé£ã®æå·åæŒç®ã«ãã£ãŠé·ãã³ãŒãåãããæååã«å€æãããŸããã€ãŸããããã·ã¥ããããã¹ã¯ãŒããåãåã£ã人ã¯ãããã䜿çšããŠå
ã®ãã¹ã¯ãŒããååŸã§ããŸããã è¿œå ã®æ段ãšããŠãåããã¹ã¯ãŒããè€æ°å䜿çšãããšãç°ãªãçµæãåŸãããããã2人ã®ãŠãŒã¶ãŒãããã·ã¥ãèŠãŠåããã¹ã¯ãŒããæã£ãŠãããã©ãããå€æããããšã¯ã§ããŸããã
æ€èšŒããã»ã¹ã¯ã次ã®ããã«Werkzeugã®2çªç®ã®é¢æ°ã䜿çšããŠå®è¡ãããŸãã
>>> from werkzeug.security import check_password_hash >>> check_password_hash(hash, 'foobar') True >>> check_password_hash(hash, 'barfoo') False
æ€èšŒæ©èœã¯ã以åã«çæããããã¹ã¯ãŒããšããã°ã€ã³äžã«ãŠãŒã¶ãŒãå
¥åãããã¹ã¯ãŒãã®ããã·ã¥ãåãå
¥ããŸãã ãã®é¢æ°ã¯ããŠãŒã¶ãŒãæå®ãããã¹ã¯ãŒããããã·ã¥ãšäžèŽããå Žåã¯True
ãããã§ãªãå Žåã¯False
è¿ããŸãã
ãã¹ãŠã®ãã¹ã¯ãŒãããã·ã¥ããžãã¯ã¯ããŠãŒã¶ãŒã¢ãã«ã®2ã€ã®æ°ããã¡ãœãããšããŠå®è£
ã§ããŸãã
app/models.py
ïŒããã·ã¥ãšãã¹ã¯ãŒãæ€èšŒ
from werkzeug.security import generate_password_hash, check_password_hash
ããã2ã€ã®æ¹æ³ã䜿çšãããšããŠãŒã¶ãŒãªããžã§ã¯ãã¯å
ã®ãã¹ã¯ãŒããä¿åããããšãªããå®å
šãªãã¹ã¯ãŒããã§ãã¯ãå®è¡ã§ããããã«ãªããŸããã ãããã®æ°ããã¡ãœããã®äœ¿çšäŸã次ã«ç€ºããŸãã
>>> u = User(username='susan', email='susan@example.com') >>> u.set_password('mypassword') >>> u.check_password('anotherpassword') False >>> u.check_password('mypassword') True
Flask-Loginã®æŠèŠ
ãã®ç« ã§ã¯ãFlask-LoginãšåŒã°ããéåžžã«äººæ°ã®ããFlaskæ¡åŒµæ©èœã玹ä»ããŸãã ãã®æ¡åŒµæ©èœã¯ããŠãŒã¶ãŒã®ãã°ã€ã³ç¶æ
ãå¶åŸ¡ããããšãã°ããŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã«ãã°ã€ã³ããã¢ããªã±ãŒã·ã§ã³ããŠãŒã¶ãŒã®ãã°ã€ã³ããèšæ¶ããããŸã§å¥ã®ããŒãžã«ç§»åã§ããããã«ããŸãã ãŸããRemember Meæ©èœãæäŸããŸããããã«ããããŠãŒã¶ãŒã¯ãã©ãŠã¶ãŒãŠã£ã³ããŠãéããåŸã§ããã°ã€ã³ãããŸãŸã«ã§ããŸãã ãã®ç« ã®æºåãããã«ã¯ãä»®æ³ç°å¢ã«Flask-Loginãã€ã³ã¹ããŒã«ããããšããå§ããŸãã
(venv) $ pip install flask-login
ä»ã®æ¡åŒµæ©èœãšåæ§ãFlask-Loginã¯app/__init__.py
ã¢ããªã±ãŒã·ã§ã³ã€ã³ã¹ã¿ã³ã¹ã®çŽåŸã«äœæããã³åæåããå¿
èŠããããŸãã ãããã£ãŠããã®æ¡åŒµæ©èœã¯åæåãããŸãã
app/__init__.py
åæå
# ... from flask_login import LoginManager app = Flask(__name__) # ... login = LoginManager(app) # ...
Flask-Loginçšã®ãŠãŒã¶ãŒã¢ãã«ã®æºå
Flask-Loginæ¡åŒµæ©èœã¯ãã«ã¹ã¿ã ã¢ããªã±ãŒã·ã§ã³ã¢ãã«ã§åäœããç¹å®ã®ããããã£ãšã¡ãœãããããã«å®è£
ãããããšãæ³å®ããŠããŸãã ãã®ã¢ãããŒãã¯ããããã®å¿
èŠãªèŠçŽ ãã¢ãã«ã«è¿œå ãããéããFlask-Loginã«ã¯ä»ã®èŠä»¶ããªããããããšãã°ãããŒã¿ããŒã¹ã·ã¹ãã ã«åºã¥ãããŠãŒã¶ãŒã¢ãã«ã§åäœã§ãããšããç¹ã§åªããŠããŸãã
4ã€ã®å¿
é èŠçŽ ã以äžã«ãªã¹ãããŸãã
is_authenticated
ïŒãŠãŒã¶ãŒã«æå¹ãªè³æ Œæ
å ±ãããå Žåã¯True
ãããã§ãªãå Žåã¯False
ãªãããããã£ãis_active
ïŒãŠãŒã¶ãŒã¢ã«ãŠã³ããã¢ã¯ãã£ããªå Žåã¯True
ãè¿ããããã§ãªãå Žåã¯False
ãè¿ãããããã£ãis_anonymous
ïŒéåžžã®ãŠãŒã¶ãŒã®å Žåã¯False
ãè¿ãããŠãŒã¶ãŒãå¿åã®å Žåã¯True
ãè¿ãããããã£ãget_id()
ïŒãŠãŒã¶ãŒã®äžæã®èå¥åãæååãšããŠè¿ãã¡ãœããïŒPython 2ã䜿çšããŠããå Žåã¯ãŠãã³ãŒãïŒã
4ã€ãã¹ãŠãç°¡åã«å®è£
ã§ããŸãããå®è£
ã¯ããªãäžè¬çã§ãããããFlask-Loginã¯ãŠãŒã¶ãŒã¯ã©ã¹ã®ã»ãšãã©ã®ã¯ã©ã¹ã«é©ããäžè¬çãªå®è£
ãå«ãããã¯ã¹ã€ã³ã¯ã©ã¹UserMixin
æäŸããŸãã ããã¯ã ããã¯ã¹ã€ã³ã¯ã©ã¹ãã¢ãã«ã«è¿œå ãããæ¹æ³ã§ãã
app/models.py
ãŠãŒã¶ãŒããã¯ã¹ã€ã³ã¯ã©ã¹
# ... from flask_login import UserMixin class User(UserMixin, db.Model): # ...
ã«ã¹ã¿ã ããŒããŒ
Flask-Loginã¯ãã¢ããªã±ãŒã·ã§ã³ã«æ¥ç¶ããåãŠãŒã¶ãŒã«å²ãåœãŠãããFlask ãŠãŒã¶ãŒã»ãã·ã§ã³ã«äžæã®èå¥åãä¿åããããšã«ãããç»é²ãŠãŒã¶ãŒã远跡ããŸãã ãã°ãªã³ããŠãããŠãŒã¶ãŒãæ°ããããŒãžã«ã¢ã¯ã»ã¹ãããã³ã«ãFlask-Loginã¯ã»ãã·ã§ã³ãããŠãŒã¶ãŒIDãååŸãããã®ãŠãŒã¶ãŒãã¡ã¢ãªã«ããŒãããŸãã
Flask-Loginã¯ããŒã¿ããŒã¹ã«ã€ããŠäœãç¥ããªãããããŠãŒã¶ãŒãããŒããããšãã«ã¢ããªã±ãŒã·ã§ã³ã®å©ããå¿
èŠã§ãã ãã®ãããæ¡åŒµæ©èœã¯ãã¢ããªã±ãŒã·ã§ã³ããŠãŒã¶ãŒããŒãããŒããŒæ©èœãèšå®ããããšãæ³å®ããŠããŸãããã®æ©èœã¯ããŠãŒã¶ãŒã«èå¥åãããŒãããããã«åŒã³åºãããšãã§ããŸãã ãã®é¢æ°ã¯app / models.pyã¢ãžã¥ãŒã«ã«è¿œå ã§ããŸã ïŒ
app/models.py
ãŠãŒã¶ãŒããŒããŒæ©èœ
from app import login # ... @login.user_loader def load_user(id): return User.query.get(int(id))
ãŠãŒã¶ãŒããŒãããŒããŒã¯ã @login.user_loader
ãã³ã¬ãŒã¿ãŒã䜿çšããŠFlask-Loginã«ç»é²ãããŸãã Flask-LoginãåŒæ°ãšããŠé¢æ°ã«æž¡ãèå¥åã¯æååã«ãªããŸãããã®ãããæ°å€èå¥åã䜿çšããããŒã¿ããŒã¹ã§ã¯ãäžèšã®int(id)
ããã«ãæååãæŽæ°ã«å€æããå¿
èŠããããŸãã
ãŠãŒã¶ãŒãã°ã€ã³
ãã°ã€ã³æ©èœã«ç§»ããŸããããããã¯ãæãåºãããã«ã flash()
ã¡ãã»ãŒãžã®ã¿ãçºè¡ããåœã®ãã°ã€ã³ãå®è£
ããŸããã ããã§ãã¢ããªã±ãŒã·ã§ã³ã¯ãŠãŒã¶ãŒããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ãããã¹ã¯ãŒãããã·ã¥ãäœæããã³ç¢ºèªããæ¹æ³ãç¥ã£ãã®ã§ããã®ãã©ãŠãžã³ã°æ©èœãå®äºããããšãã§ããŸãïŒ \microblog\app\routes.py
ïŒã
app/routes.py
ïŒãã°ã€ã³ãã¥ãŒé¢æ°ã®ããžãã¯
# ... from flask_login import current_user, login_user from app.models import User # ... @app.route('/login', methods=['GET', 'POST']) def login(): if current_user.is_authenticated: return redirect(url_for('index')) form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.username.data).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) return redirect(url_for('index')) return render_template('login.html', title='Sign In', form=form)
login()
é¢æ°ã®æåã®2è¡ã¯ãå¥åŠãªç¶æ³ã«ã€ãªããlogin()
ã ãã°ã€ã³ããŠããŠãã¢ããªã±ãŒã·ã§ã³ã®/login
URLã«ã¢ã¯ã»ã¹ããããŠãŒã¶ãŒããããšæ³åãããšãèªèšŒããŒãžã«ãªãã€ã¬ã¯ããããŸãã æããã«ãããã¯ééããªã®ã§ããããèš±å¯ããããããŸããã current_user
å€æ°ã¯Flask-LoginããååŸããããã€ã§ããŠãŒã¶ãŒãªããžã§ã¯ããååŸããããã«äœ¿çšã§ããŸãã ãã®å€æ°ã®å€ã¯ãããŒã¿ããŒã¹ã®ãŠãŒã¶ãŒãªããžã§ã¯ãïŒFlask-Loginãäžèšã®ãŠãŒã¶ãŒããŒããŒã³ãŒã«ããã¯ãä»ããŠèªã¿åãïŒããŸãã¯ãŠãŒã¶ãŒããŸã ãã°ã€ã³ããŠããªãå Žåã¯ç¹å¥ãªå¿åãŠãŒã¶ãŒãªããžã§ã¯ãã§ãã FlaskããŠãŒã¶ãŒãªããžã§ã¯ãã§å¿
èŠãšããããããã£ãèŠããŠããŸããïŒ ãããã®1ã€ã¯is_authenticated
ãããã¯ããŠãŒã¶ãŒãç»é²ãããŠãããã©ããã確èªããã®ã«éåžžã«äŸ¿å©ã§ãã ãŠãŒã¶ãŒãæ¢ã«ãã°ã€ã³ããŠããå Žåã¯ãåã«ã€ã³ããã¯ã¹ããŒãžã«ãªãã€ã¬ã¯ãããŸãã
以åã«äœ¿çšããflashïŒïŒãåŒã³åºã代ããã«ãå®éã«ãŠãŒã¶ãŒã®ã·ã¹ãã ã«ãã°ã€ã³ã§ããŸãã æåã®ã¹ãããã¯ãããŒã¿ããŒã¹ãããŠãŒã¶ãŒãããŒãããããšã§ãã ãŠãŒã¶ãŒåã¯éä¿¡ãã©ãŒã ã«ä»å±ããŠãããããããŒã¿ããŒã¹ãç
§äŒããŠãŠãŒã¶ãŒãèŠã€ããããšãã§ããŸãã
ãããè¡ãã«ã¯ãSQLAlchemyã¯ãšãªãªããžã§ã¯ãã®filter_by()
ã¡ãœããã䜿çšããŸãã filter_by()
ã®çµæã¯ãäžèŽãããŠãŒã¶ãŒåãæã€ãªããžã§ã¯ãã®ã¿ãå«ãã¯ãšãªã§ãã çµæã1ã€ãŸãã¯0ã«ãªãããšãç¥ã£ãŠããã®ã§ã first()
åŒã³åºããŠèŠæ±ãçµäºããŸããããã¯ãååšããå Žåã¯ãŠãŒã¶ãŒãªããžã§ã¯ããè¿ããååšããªãå Žåã¯None
ãè¿ããŸãã 第4ç« ã§ã¯ãã¯ãšãªã§all()
ã¡ãœãããåŒã³åºããšãã¯ãšãªãå®è¡ããããã®ã¯ãšãªã«äžèŽãããã¹ãŠã®çµæã®ãªã¹ããååŸããããšãããããŸããã first()
ã¡ãœããã¯ã1ã€ã®çµæã®ã¿ãå¿
èŠãªå Žåã«ã¯ãšãªãå®è¡ããå¥ã®æ¹æ³ã§ãã
æäŸããããŠãŒã¶ãŒåãšäžèŽããå Žåããã©ãŒã ã«ä»å±ããŠãããã¹ã¯ãŒããæå¹ãã©ããã確èªã§ããŸãã ããã¯ãäžèšã§å®çŸ©ããcheck_password()
ã¡ãœãããåŒã³åºãããšã§å®è¡ãããŸãã ããã«ããããŠãŒã¶ãŒãããã·ã¥ãã¹ã¯ãŒããä¿åãããã©ãŒã ã«å
¥åãããã¹ã¯ãŒããããã·ã¥ãšäžèŽãããã©ãããå€æããŸãã ãã®ããã2ã€ã®ãšã©ãŒæ¡ä»¶ãèããããŸãããŠãŒã¶ãŒåãç¡å¹ã§ãããããŠãŒã¶ãŒã®ãã¹ã¯ãŒããæ£ãããªãå¯èœæ§ããããŸãã ãããã®å ŽåãããŠãŒã¶ãŒãåè©Šè¡ã§ããããã«ãã¡ãã»ãŒãžãã¹ã¯ããŒã«ããŠãã°ã€ã³ããã³ããã«ãªãã€ã¬ã¯ãããŸãã
ãŠãŒã¶ãŒåãšãã¹ã¯ãŒããæ£ããå ŽåãFlask-Loginããlogin_user()
é¢æ°ãåŒã³åºããŸãã ãã®é¢æ°ã¯ãã°ã€ã³æã«ãŠãŒã¶ãŒãç»é²ããããããã®ãŠãŒã¶ãŒã®current_user
å€æ°ã¯ããŠãŒã¶ãŒãcurrent_user
ããå°æ¥ã®ããŒãžã§èšå®ãããŸãã
ãã°ã€ã³ããã»ã¹ãå®äºããã«ã¯ãæ°ããç»é²ãããŠãŒã¶ãŒãã€ã³ããã¯ã¹ããŒãžã«ãªãã€ã¬ã¯ãããã ãã§ãã
ãã°ã¢ãŠã
æããã«ãã¢ããªã±ãŒã·ã§ã³ãçµäºãããªãã·ã§ã³ããŠãŒã¶ãŒã«æäŸããå¿
èŠããããŸãã ããã¯ãFlask-Loginã®logout_user()
é¢æ°ã䜿çšããŠlogout_user()
ã§ããŸãã exité¢æ°ã¯æ¬¡ã®ããã«ãªããŸãã
app/routes.py
ïŒãã°ã¢ãŠããã¥ãŒæ©èœ
# ... from flask_login import logout_user # ... @app.route('/logout') def logout(): logout_user() return redirect(url_for('index'))
ãŠãŒã¶ãŒããã°ã€ã³ããåŸãããã²ãŒã·ã§ã³ããŒã®login
ãªã³ã¯ãèªåçã«logout
ãªã³ã¯ã«åãæ¿ããããšãã§ããŸãã ããã¯ã base.htmlãã³ãã¬ãŒãã®æ¡ä»¶åŒã䜿çšããŠå®è¡ã§ããŸãã
app/templates/base.html
ïŒæ¡ä»¶ä»ããã°ã€ã³ããã³ãã°ã¢ãŠããªã³ã¯
<div> Microblog: <a href="{{ url_for('index') }}">Home</a> {% if current_user.is_anonymous %} <a href="{{ url_for('login') }}">Login</a> {% else %} <a href="{{ url_for('logout') }}">Logout</a> {% endif %} </div>
is_anonymous
ããããã£ã¯ãFlask-LoginãUserMixinã¯ã©ã¹ãéããŠãŠãŒã¶ãŒãªããžã§ã¯ãã«è¿œå ããå±æ§ã®1ã€ã§ãã åŒcurrent_user.is_anonymous
ã¯ããŠãŒã¶ãŒããã°ã€ã³ããŠããªãå Žåã«ã®ã¿True
ãè¿ããŸãã
ãŠãŒã¶ãŒãã°ã€ã³èŠä»¶
Flask-Loginã¯ãã¢ããªã±ãŒã·ã§ã³ã®ç¹å®ã®ããŒãžã衚瀺ããåã«ãŠãŒã¶ãŒã«ç»é²ã匷å¶ããéåžžã«äŸ¿å©ãªæ©èœãæäŸããŸãã ãã°ã€ã³ããŠããªããŠãŒã¶ãŒãå®å
šãªããŒãžã衚瀺ããããšãããšãFlask-Loginã¯èªåçã«ãŠãŒã¶ãŒããã°ã€ã³ãã©ãŒã ã«ãªãã€ã¬ã¯ãããŸãããã°ã€ã³ããã»ã¹ãå®äºãããšããŠãŒã¶ãŒã衚瀺ãããããŒãžã«ãªãã€ã¬ã¯ããããŸãã
ãã®é¢æ°ãå®è£
ããã«ã¯ãFlask-Loginã¯ãã°ã€ã³ãåŠçãããã¥ãŒé¢æ°ãäœã§ããããç¥ã£ãŠããå¿
èŠããããŸãã ããã¯app / init .pyã«è¿œå ã§ããŸãïŒ
# ... login = LoginManager(app) login.login_view = 'login'
äžèšã®ããã°ã€ã³ãå€ã¯ããã°ã€ã³ããããã®é¢æ°ïŒãŸãã¯ãšã³ããã€ã³ãïŒã®ååã§ãã ã€ãŸããURLãååŸããããã«url_for()
åŒã³åºãã§äœ¿çšããååã
Flask-Loginã¡ãœããã¯ã @login_required
ãšãããã³ã¬ãŒã¿ãŒã䜿çšããŠãå¿åãŠãŒã¶ãŒãããã©ãŠãžã³ã°æ©èœãä¿è·ããŸãã Flaskã®@app.route
ãã³ã¬ãŒã¿ãŒã®äžã®ãã¥ãŒé¢æ°ã«ãã®ãã³ã¬ãŒã¿ãŒãè¿œå ãããšãé¢æ°ã¯ä¿è·ãããèªèšŒãããŠããªããŠãŒã¶ãŒãžã®ã¢ã¯ã»ã¹ãèš±å¯ãããªããªããŸãã ãã³ã¬ãŒã¿ãã¢ããªã±ãŒã·ã§ã³ã€ã³ããã¯ã¹ãã¥ãŒé¢æ°ã«é©çšããæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
app/routes.py
ãã³ã¬ãŒã¿ãŒ
from flask_login import login_required @app.route('/') @app.route('/index') @login_required def index(): # ...
ãã°ã€ã³ã®æåããããŠãŒã¶ãŒãã¢ã¯ã»ã¹ãããããŒãžãžã®ãªãã€ã¬ã¯ããå®è£
ããããšã¯æ®ã£ãŠããŸãã ãã°ã€ã³ããŠããªããŠãŒã¶ãŒã@login_required
ãã³ãŒããŒã«ãã£ãŠä¿è·ãããŠãããã©ãŠãžã³ã°æ©èœã«ã¢ã¯ã»ã¹ãããšããã³ã¬ãŒã¿ãŒã¯ãã°ã€ã³ããŒãžã«ãªãã€ã¬ã¯ãããããšããŸãããã¢ããªã±ãŒã·ã§ã³ãæåã®ããŒãžã«æ»ãããšãã§ããããã«ããã®ãªãã€ã¬ã¯ãã«è¿œå æ
å ±ãå«ãŸããŸãã ããšãã°ããŠãŒã¶ãŒã/ indexã«ç§»åãããšã @login_required
ãã³ãã©ãŒ@login_required
ãªã¯ãšã¹ã@login_required
ã€ã³ã¿ãŒã»ãããã /login
ãžã®ãªãã€ã¬ã¯ãã§å¿çããŸããããã®URLã«ã¯ãšãªæåååŒæ°ãè¿œå ããŠãå®å
šãªURL / loginïŒNext = / indexãäœæããŸã ã ã¯ãšãªæåånext
åŒæ°ã¯ãœãŒã¹URLã«èšå®ããããããã¢ããªã±ãŒã·ã§ã³ã¯ããã䜿çšããŠãã°ã€ã³åŸã«ãªãã€ã¬ã¯ãã§ããŸãã
次ã«ã next
ã¯ãšãªæåååŒæ°ãèªã¿åã£ãŠåŠçããæ¹æ³ã瀺ãã³ãŒãã¹ããããã瀺ããŸãã
app/routes.py
ïŒã次ã®ãããŒãžã«ãªãã€ã¬ã¯ãããŸã
from flask import request from werkzeug.urls import url_parse @app.route('/login', methods=['GET', 'POST']) def login(): # ... if form.validate_on_submit(): user = User.query.filter_by(username=form.username.data).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) next_page = request.args.get('next') if not next_page or url_parse(next_page).netloc != '': next_page = url_for('index') return redirect(next_page) # ...
Flask-Loginããlogin_user()
é¢æ°ãåŒã³åºããŠãŠãŒã¶ãŒããã°ã€ã³ããçŽåŸã«ãã¯ãšãªæååã®next
åŒæ°ã®å€ãåãåããŸãã Flaskã«ã¯ãã¯ã©ã€ã¢ã³ãããªã¯ãšã¹ããšãšãã«éä¿¡ãããã¹ãŠã®æ
å ±ãå«ããªã¯ãšã¹ãå€æ°ãå«ãŸããŠããŸãã ç¹ã«ã request.args
å±æ§ã¯ã request.args
èŸæžåœ¢åŒã§ã¯ãšãªæååã®å
容ãæäŸããŸãã å®éã«ããã°ã€ã³ãæåããåŸã«ãªãã€ã¬ã¯ãããå Žæã決å®ããããã«èæ
®ããå¿
èŠããã3ã€ã®å¯èœãªã±ãŒã¹ããããŸãã
- ãã°ã€ã³URLã«æ¬¡ã®åŒæ°ããªãå ŽåããŠãŒã¶ãŒã¯ã€ã³ããã¯ã¹ããŒãžã«ãªãã€ã¬ã¯ããããŸãã
- ãã°ã€ã³URLã«
next
åŒæ°ãå«ãŸããŠããããããçžå¯Ÿãã¹ïŒã€ãŸãããã¡ã€ã³ã®äžéšãå«ãŸãªãURLïŒã«èšå®ãããŠããå ŽåããŠãŒã¶ãŒã¯ãã®URLã«ãªãã€ã¬ã¯ããããŸãã - ãã°ã€ã³URLã«
next
åŒæ°ãå«ãŸããŠããŠããã¡ã€ã³åãå«ãå®å
šãªURLã«èšå®ãããŠããå ŽåããŠãŒã¶ãŒã¯ã€ã³ããã¯ã¹ããŒãžã«ãªãã€ã¬ã¯ããããŸãã
æåãš2çªç®ã®ã±ãŒã¹ã§ã¯ã説æã¯äžèŠã§ãã 3çªç®ã®ã±ãŒã¹ã¯ãã¢ããªã±ãŒã·ã§ã³ãããå®å
šã«ããããšã§ãã æ»æè
ã¯æªæã®ãããµã€ããžã®URLãnext
åŒæ°ã«æ¿å
¥ã§ãããããã¢ããªã±ãŒã·ã§ã³ã¯URLããªãã€ã¬ã¯ãããã ãã§ããããã«ããããªãã€ã¬ã¯ãã¯ã¢ããªã±ãŒã·ã§ã³ãšåããµã€ãã«ç¢ºå®ã«æ®ããŸãã URLãçžå¯Ÿã絶察ããå€æããã«ã¯ã Werkzeugã® url_parse()
é¢æ°ã䜿çšããŠåæãã netloc
ã³ã³ããŒãã³ããnetloc
ãã©ããã確èªããŸãã
ãã°ã€ã³ãããŠãŒã¶ãŒããã³ãã¬ãŒãã«è¡šç€ºãã
第2ç« ã«æ»ã£ãŠããŠãŒã¶ãŒãµãã·ã¹ãã ãäœæãããåã«ã¢ããªã±ãŒã·ã§ã³ã®ããŒã ããŒãžãéçºããããã«åœã®ãŠãŒã¶ãŒãäœæããããšãèŠããŠããŸããïŒ ããŠãã¢ããªã±ãŒã·ã§ã³ã«ã¯å®éã®ãŠãŒã¶ãŒãããã®ã§ãåœã®ãŠãŒã¶ãŒãåé€ããŠãå®éã®ãŠãŒã¶ãŒãšã®äœæ¥ãéå§ã§ããŸãã åœç©ã®ä»£ããã«ããã³ãã¬ãŒãã§Flask-Login-s current_userã䜿çšã§ããŸãã
app/templates/index.html
ïŒçŸåšã®ãŠãŒã¶ãŒããã³ãã¬ãŒãã«æž¡ããŸã
{% extends "base.html" %} {% block content %} <h1>Hi, {{ current_user.username }}!</h1> {% for post in posts %} <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div> {% endfor %} {% endblock %}
ãããŠã view
é¢æ°ã§user
åŒæ°ãåé€ã§ããŸãïŒ microblog \ app \ routes.py ïŒïŒ
app / routes.pyïŒãŠãŒã¶ãŒããã³ãã¬ãŒãã«æž¡ããªã
@app.route('/') @app.route('/index') def index(): # ... return render_template("index.html", title='Home Page', posts=posts)
å
¥åãšåºåã®æäœæ§ããã§ãã¯ããã®ã«ãµããããæãæ¥ãããã§ãã ãŠãŒã¶ãŒç»é²ããŸã äžè¶³ããŠãããããããŒã¿ããŒã¹ã«ãŠãŒã¶ãŒãè¿œå ããå¯äžã®æ¹æ³ã¯ãPythonã·ã§ã«ãä»ããŠè¡ãããšã§ãããã®ããã flask shell
ãå®è¡ãã次ã®ã³ãã³ããå
¥åããŠãŠãŒã¶ãŒãç»é²ããŸãã
>>> u = User(username='susan', email='susan@example.com') >>> u.set_password('cat') >>> db.session.add(u) >>> db.session.commit()
ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããŠhttp:// localhost:5000/
ãŸãã¯http://localhost:5000/index
ã«ã¢ã¯ã»ã¹ããããšãããšãããã«ãã°ã€ã³ããŒãžã«ãªãã€ã¬ã¯ããããŸãã ãããŠãããŒã¿ããŒã¹ã«è¿œå ãããŠãŒã¶ãŒã®è³æ Œæ
å ±ã䜿çšããŠããã°ã€ã³æé ãå®äºãããšãããŒãœãã©ã€ãºãããæšæ¶ã衚瀺ãããå
ã®ããŒãžã«æ»ããŸãã
ãŠãŒã¶ãŒç»é²
ãã®ç« ã§äœæããæ©èœã®æåŸã®éšåã¯ããŠãŒã¶ãŒãWebãã©ãŒã ããç»é²ã§ããããã«ããããã®ç»é²ãã©ãŒã ã§ãã app / forms.pyã§Webãã©ãŒã ã¯ã©ã¹ãäœæããããšããå§ããŸãããã
from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import ValidationError, DataRequired, Email, EqualTo from app.models import User # ... class RegistrationForm(FlaskForm): username = StringField('Username', validators=[DataRequired()]) email = StringField('Email', validators=[DataRequired(), Email()]) password = PasswordField('Password', validators=[DataRequired()]) password2 = PasswordField( 'Repeat Password', validators=[DataRequired(), EqualTo('password')]) submit = SubmitField('Register') def validate_username(self, username): user = User.query.filter_by(username=username.data).first() if user is not None: raise ValidationError('Please use a different username.') def validate_email(self, email): user = User.query.filter_by(email=email.data).first() if user is not None: raise ValidationError('Please use a different email address.')
ãã®æ°ãããã©ãŒã ã«ã¯ãæ€èšŒã«é¢é£ããèå³æ·±ãããšãããã€ããããŸãã ãŸããã¡ãŒã«ã®ã¡ãŒã«ãã£ãŒã«ãã«email
DataRequiredã®åŸã«Emailãšãã2çªç®ã®ããªããŒã¿ãŒãè¿œå ããŸããã ããã¯ãWTFormsã«ä»å±ããå¥ã®ããªââããŒã¿ãŒïŒå
ã®ãã¹ããã¯ããªããŒã¿ãŒããã€ãŸãçµã¿èŸŒã¿ã®æšæºãšããŠç¿»èš³ããæ¹ãæ£ããïŒã§ããããã«ããããŠãŒã¶ãŒããã®ãã£ãŒã«ãã«å
¥åããå
容ãã¡ãŒã«ã¢ãã¬ã¹ã®æ§é ãšäžèŽããããã«ãªããŸãã
ããã¯ç»é²ãã©ãŒã ã§ãããããã¿ã€ããã¹ã®ãªã¹ã¯ã軜æžããããã«ããŠãŒã¶ãŒã«ãã¹ã¯ãŒãã2åå
¥åããããã«äŸé Œããã®ãéåžžã§ãã ãã®ããã password
ãšpassword2
ãããpassword2
ã 2çªç®ã®ãã¹ã¯ãŒããã£ãŒã«ãã¯ãå¥ã®æšæºEqualToããªããŒã¿ã䜿çšããŸããããã¯ããã®å€ãæåã®ãã¹ã¯ãŒããã£ãŒã«ãã®å€ãšåäžã§ããããšã確èªããŸãã
ãŸãããã®ã¯ã©ã¹ã«validate_username()
ããã³validate_email()
2ã€ã®ã¡ãœãããè¿œå ããŸããã validate_<_>
ãã¿ãŒã³ã«äžèŽããã¡ãœãããè¿œå ãããšãWTFormsã¯ããããã«ã¹ã¿ã ããªããŒã¿ãŒãšããŠåãå
¥ããæšæºããªããŒã¿ãŒã«å ããŠããããåŒã³åºããŸãã ãã®å ŽåããŠãŒã¶ãŒãå
¥åãããŠãŒã¶ãŒåãšé»åã¡ãŒã«ã¢ãã¬ã¹ãæ¢ã«ããŒã¿ããŒã¹ã«ãªãããšã確èªãããã®ã§ããããã®2ã€ã®æ¹æ³ã¯ããŒã¿ããŒã¹ã«ã¯ãšãªãçºè¡ããçµæããªãããšãæåŸ
ããŸãã , , ValidationError . , , , .
-, HTML-, app/templates/register.html . , :
{% extends "base.html" %} {% block content %} <h1>Register</h1> <form action="" method="post"> {{ form.hidden_tag() }} <p> {{ form.username.label }}<br> {{ form.username(size=32) }}<br> {% for error in form.username.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p> {{ form.email.label }}<br> {{ form.email(size=64) }}<br> {% for error in form.email.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p> {{ form.password.label }}<br> {{ form.password(size=32) }}<br> {% for error in form.password.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p> {{ form.password2.label }}<br> {{ form.password2(size=32) }}<br> {% for error in form.password2.errors %} <span style="color: red;">[{{ error }}]</span> {% endfor %} </p> <p>{{ form.submit() }}</p> </form> {% endblock %}
, , :
<p>New User? <a href="{{ url_for('register') }}">Click to Register!</a></p>
, , , app/routes.py :
from app import db from app.forms import RegistrationForm # ... @app.route('/register', methods=['GET', 'POST']) def register(): if current_user.is_authenticated: return redirect(url_for('index')) form = RegistrationForm() if form.validate_on_submit(): user = User(username=form.username.data, email=form.email.data) user.set_password(form.password.data) db.session.add(user) db.session.commit() flash('Congratulations, you are now a registered user!') return redirect(url_for('login')) return render_template('register.html', title='Register', form=form)
, . , . , if validate_on_submit()
, , , , .
<<<å 次>>>