Your task is to create simple web application which will track your sport activity.
Content of config.py
Content of .travis.yml
Content of tests/test_math.py:
Content of app/__init__.py:
Content of activity.py
Content of app/models.py
Content of test/test_user_model.py:
Content of app/auth/__init.py:
Content of app/auth/views.py:
Content of app/auth/forms.py:
Content of app/templates/base.html:
Content of apps/templates/auth/login.html
{ "data": { "sessionMaterial": { "id": "session-material:2019/tieto-ostrava-jaro:regular-expressions:2", "title": "Final Assignment", "html": "\n \n \n\n <h2>Final Assignment</h2>\n<p>Your task is to create simple web application which will track your sport activity.</p>\n<h3>Assignment steps</h3>\n<ol>\n<li>Create GitHub repository for your project</li>\n<li>Install locally on your laptop Flask</li>\n</ol>\n<div class=\"solution\" id=\"solution-0\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/0/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span>python -m venv venv\n<span class=\"nb\">source</span> venv/bin/activate\npip install flask\n</pre></div>\n </div>\n</div><ol>\n<li>Create project structure for Flask application</li>\n</ol>\n<div class=\"solution\" id=\"solution-1\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/1/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"p\">|</span>-activity\n <span class=\"p\">|</span>-app/\n <span class=\"p\">|</span>-templates/\n <span class=\"p\">|</span>-static/\n <span class=\"p\">|</span>-main/\n <span class=\"p\">|</span>-__init__.py\n <span class=\"p\">|</span>-errors.py\n <span class=\"p\">|</span>-forms.py\n <span class=\"p\">|</span>-views.py\n <span class=\"p\">|</span>-__init__.py\n <span class=\"p\">|</span>-email.py\n <span class=\"p\">|</span>-models.py\n <span class=\"p\">|</span>-migrations/\n <span class=\"p\">|</span>-tests/\n <span class=\"p\">|</span>-__init__.py\n <span class=\"p\">|</span>-test*.py\n <span class=\"p\">|</span>-venv/\n <span class=\"p\">|</span>-requirements.txt\n <span class=\"p\">|</span>-config.py\n <span class=\"p\">|</span>-activity.py\n\n\nmkdir <span class=\"o\">{</span>app,migrations,tests<span class=\"o\">}</span>\nmkdir app/<span class=\"o\">{</span>templates,static,main<span class=\"o\">}</span>\ntouch requirements.txt\ntouch config.py\ntouch activity.py\ntouch app/__init__.py\ntouch app/main/__init__.py\n</pre></div>\n </div>\n</div><p>Content of config.py</p>\n<div class=\"solution\" id=\"solution-2\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/2/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">os</span>\n<span class=\"n\">basedir</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">abspath</span><span class=\"p\">(</span><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">dirname</span><span class=\"p\">(</span><span class=\"vm\">__file__</span><span class=\"p\">))</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">Config</span><span class=\"p\">:</span>\n <span class=\"n\">SECRET_KEY</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'SECRET_KEY'</span><span class=\"p\">)</span> <span class=\"ow\">or</span> <span class=\"s1\">'hard to guess string'</span>\n <span class=\"n\">MAIL_SERVER</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'MAIL_SERVER'</span><span class=\"p\">,</span> <span class=\"s1\">'smtp.googlemail.com'</span><span class=\"p\">)</span>\n <span class=\"n\">MAIL_PORT</span> <span class=\"o\">=</span> <span class=\"nb\">int</span><span class=\"p\">(</span><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'MAIL_PORT'</span><span class=\"p\">,</span> <span class=\"s1\">'587'</span><span class=\"p\">))</span>\n <span class=\"n\">MAIL_USE_TLS</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'MAIL_USE_TLS'</span><span class=\"p\">,</span> <span class=\"s1\">'true'</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">lower</span><span class=\"p\">()</span> <span class=\"ow\">in</span> \\\n <span class=\"p\">[</span><span class=\"s1\">'true'</span><span class=\"p\">,</span> <span class=\"s1\">'on'</span><span class=\"p\">,</span> <span class=\"s1\">'1'</span><span class=\"p\">]</span>\n <span class=\"n\">MAIL_USERNAME</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'MAIL_USERNAME'</span><span class=\"p\">)</span>\n <span class=\"n\">MAIL_PASSWORD</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'MAIL_PASSWORD'</span><span class=\"p\">)</span>\n <span class=\"n\">ACTIVITY_MAIL_SUBJECT_PREFIX</span> <span class=\"o\">=</span> <span class=\"s1\">'[Activity]'</span>\n <span class=\"n\">ACTIVITY_MAIL_SENDER</span> <span class=\"o\">=</span> <span class=\"s1\">'Activity Admin <activity@example.com>'</span>\n <span class=\"n\">ACTIVITY_ADMIN</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'ACTIVITY_ADMIN'</span><span class=\"p\">)</span>\n <span class=\"n\">SQLALCHEMY_TRACK_MODIFICATIONS</span> <span class=\"o\">=</span> <span class=\"bp\">False</span>\n\n <span class=\"nd\">@staticmethod</span>\n <span class=\"k\">def</span> <span class=\"nf\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">):</span>\n <span class=\"k\">pass</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">DevelopmentConfig</span><span class=\"p\">(</span><span class=\"n\">Config</span><span class=\"p\">):</span>\n <span class=\"n\">DEBUG</span> <span class=\"o\">=</span> <span class=\"bp\">True</span>\n <span class=\"n\">SQLALCHEMY_DATABASE_URI</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'DEV_DATABASE_URL'</span><span class=\"p\">)</span> <span class=\"ow\">or</span> \\\n <span class=\"s1\">'sqlite:///'</span> <span class=\"o\">+</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">(</span><span class=\"n\">basedir</span><span class=\"p\">,</span> <span class=\"s1\">'data-dev.sqlite'</span><span class=\"p\">)</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">TestingConfig</span><span class=\"p\">(</span><span class=\"n\">Config</span><span class=\"p\">):</span>\n <span class=\"n\">TESTING</span> <span class=\"o\">=</span> <span class=\"bp\">True</span>\n <span class=\"n\">SQLALCHEMY_DATABASE_URI</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'TEST_DATABASE_URL'</span><span class=\"p\">)</span> <span class=\"ow\">or</span> \\\n <span class=\"s1\">'sqlite://'</span>\n\n<span class=\"k\">class</span> <span class=\"nc\">ProductionConfig</span><span class=\"p\">(</span><span class=\"n\">Config</span><span class=\"p\">):</span>\n <span class=\"n\">SQLALCHEMY_DATABASE_URI</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s1\">'DATABASE_URL'</span><span class=\"p\">)</span> <span class=\"ow\">or</span> \\\n <span class=\"s1\">'sqlite:///'</span> <span class=\"o\">+</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">path</span><span class=\"o\">.</span><span class=\"n\">join</span><span class=\"p\">(</span><span class=\"n\">basedir</span><span class=\"p\">,</span> <span class=\"s1\">'data.sqlite'</span><span class=\"p\">)</span>\n\n<span class=\"n\">config</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n <span class=\"s1\">'development'</span><span class=\"p\">:</span> <span class=\"n\">DevelopmentConfig</span><span class=\"p\">,</span>\n <span class=\"s1\">'testing'</span><span class=\"p\">:</span> <span class=\"n\">TestingConfig</span><span class=\"p\">,</span>\n <span class=\"s1\">'production'</span><span class=\"p\">:</span> <span class=\"n\">ProductionConfig</span><span class=\"p\">,</span>\n\n <span class=\"s1\">'default'</span><span class=\"p\">:</span> <span class=\"n\">DevelopmentConfig</span>\n<span class=\"p\">}</span>\n</pre></div>\n </div>\n</div><ol>\n<li>Integrate Travis CI/CD with your GitHub project</li>\n</ol>\n<p>Content of .travis.yml</p>\n<div class=\"solution\" id=\"solution-3\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/3/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span>dist: xenial <span class=\"c1\"># required for Python >= 3.7</span>\nlanguage: python\npython:\n - <span class=\"s2\">"3.7"</span>\n<span class=\"c1\"># command to install dependencies</span>\ninstall:\n - pip install -r requirements.txt\n<span class=\"c1\"># command to run tests</span>\nscript:\n - pytest\n</pre></div>\n </div>\n</div><p>Content of tests/test_math.py:</p>\n<div class=\"solution\" id=\"solution-4\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/4/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span>import math\n\ndef test_sqrt<span class=\"o\">()</span>:\n <span class=\"nv\">num</span> <span class=\"o\">=</span> <span class=\"m\">25</span>\n assert math.sqrt<span class=\"o\">(</span>num<span class=\"o\">)</span> <span class=\"o\">==</span> <span class=\"m\">5</span>\n</pre></div>\n </div>\n</div><p>Content of app/__init__.py:</p>\n<div class=\"solution\" id=\"solution-5\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/5/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"kn\">from</span> <span class=\"nn\">flask</span> <span class=\"kn\">import</span> <span class=\"n\">Flask</span><span class=\"p\">,</span> <span class=\"n\">render_template</span>\n<span class=\"kn\">from</span> <span class=\"nn\">flask_bootstrap</span> <span class=\"kn\">import</span> <span class=\"n\">Bootstrap</span>\n<span class=\"kn\">from</span> <span class=\"nn\">flask_mail</span> <span class=\"kn\">import</span> <span class=\"n\">Mail</span>\n<span class=\"kn\">from</span> <span class=\"nn\">flask_moment</span> <span class=\"kn\">import</span> <span class=\"n\">Moment</span>\n<span class=\"kn\">from</span> <span class=\"nn\">flask_sqlalchemy</span> <span class=\"kn\">import</span> <span class=\"n\">SQLAlchemy</span>\n<span class=\"kn\">from</span> <span class=\"nn\">config</span> <span class=\"kn\">import</span> <span class=\"n\">config</span>\n\n<span class=\"n\">bootstrap</span> <span class=\"o\">=</span> <span class=\"n\">Bootstrap</span><span class=\"p\">()</span>\n<span class=\"n\">mail</span> <span class=\"o\">=</span> <span class=\"n\">Mail</span><span class=\"p\">()</span>\n<span class=\"n\">moment</span> <span class=\"o\">=</span> <span class=\"n\">Moment</span><span class=\"p\">()</span>\n<span class=\"n\">db</span> <span class=\"o\">=</span> <span class=\"n\">SQLAlchemy</span><span class=\"p\">()</span>\n\n<span class=\"k\">def</span> <span class=\"nf\">create_app</span><span class=\"p\">(</span><span class=\"n\">config_name</span><span class=\"p\">):</span>\n <span class=\"n\">app</span> <span class=\"o\">=</span> <span class=\"n\">Flask</span><span class=\"p\">(</span><span class=\"vm\">__name__</span><span class=\"p\">)</span>\n <span class=\"n\">app</span><span class=\"o\">.</span><span class=\"n\">config</span><span class=\"o\">.</span><span class=\"n\">from_object</span><span class=\"p\">(</span><span class=\"n\">config</span><span class=\"p\">[</span><span class=\"n\">config_name</span><span class=\"p\">])</span>\n <span class=\"n\">config</span><span class=\"p\">[</span><span class=\"n\">config_name</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">)</span>\n\n <span class=\"n\">bootstrap</span><span class=\"o\">.</span><span class=\"n\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">)</span>\n <span class=\"n\">mail</span><span class=\"o\">.</span><span class=\"n\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">)</span>\n <span class=\"n\">moment</span><span class=\"o\">.</span><span class=\"n\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">)</span>\n <span class=\"n\">db</span><span class=\"o\">.</span><span class=\"n\">init_app</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">)</span>\n\n <span class=\"c1\"># attach routes and custom error pages here</span>\n\n <span class=\"k\">return</span> <span class=\"n\">app</span>\n</pre></div>\n </div>\n</div><p>Content of activity.py</p>\n<div class=\"solution\" id=\"solution-6\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/6/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"kn\">import</span> <span class=\"nn\">os</span>\n<span class=\"kn\">import</span> <span class=\"nn\">click</span>\n<span class=\"kn\">from</span> <span class=\"nn\">flask_migrate</span> <span class=\"kn\">import</span> <span class=\"n\">Migrate</span>\n<span class=\"kn\">from</span> <span class=\"nn\">app</span> <span class=\"kn\">import</span> <span class=\"n\">create_app</span><span class=\"p\">,</span> <span class=\"n\">db</span>\n\n<span class=\"nd\">@pytest.fixture</span>\n<span class=\"n\">app</span> <span class=\"o\">=</span> <span class=\"n\">create_app</span><span class=\"p\">(</span><span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">getenv</span><span class=\"p\">(</span><span class=\"s1\">'FLASK_CONFIG'</span><span class=\"p\">)</span> <span class=\"ow\">or</span> <span class=\"s1\">'default'</span><span class=\"p\">)</span>\n<span class=\"n\">migrate</span> <span class=\"o\">=</span> <span class=\"n\">Migrate</span><span class=\"p\">(</span><span class=\"n\">app</span><span class=\"p\">,</span> <span class=\"n\">db</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@app.shell_context_processor</span>\n<span class=\"k\">def</span> <span class=\"nf\">make_shell_context</span><span class=\"p\">():</span>\n <span class=\"k\">return</span> <span class=\"nb\">dict</span><span class=\"p\">(</span><span class=\"n\">db</span><span class=\"o\">=</span><span class=\"n\">db</span><span class=\"p\">)</span>\n\n<span class=\"nd\">@app.route</span><span class=\"p\">(</span><span class=\"s1\">'/'</span><span class=\"p\">)</span>\n<span class=\"k\">def</span> <span class=\"nf\">hello</span><span class=\"p\">():</span>\n <span class=\"k\">return</span> <span class=\"s2\">"Hello World!"</span>\n</pre></div>\n </div>\n</div><p>Content of app/models.py</p>\n<div class=\"solution\" id=\"solution-7\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/7/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>from werkzeug.security import generate_password_hash, check_password_hash\nfrom . import db</p>\n<p>class Role(db.Model):\n <strong>tablename</strong> = 'roles'\n id = db.Column(db.Integer, primary_key=True)\n name = db.Column(db.String(64), unique=True)\n users = db.relationship('User', backref='role', lazy='dynamic')</p>\n<div class=\"highlight\"><pre><code>def __repr__(self):\n return '<Role %r>' % self.name\n\n\n</code></pre></div><p>class User(db.Model):\n <strong>tablename</strong> = 'users'\n id = db.Column(db.Integer, primary_key=True)\n username = db.Column(db.String(64), unique=True, index=True)\n role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))\n password_hash = db.Column(db.String(128))</p>\n<div class=\"highlight\"><pre><code>@property\ndef password(self):\n raise AttributeError('password is not a readable attribute')\n\n@password.setter\ndef password(self, password):\n self.password_hash = generate_password_hash(password)\n\ndef verify_password(self, password):\n return check_password_hash(self.password_hash, password)\n\ndef __repr__(self):\n return '<User %r>' % self.username</code></pre></div>\n </div>\n</div><p>Content of test/test_user_model.py:</p>\n<div class=\"solution\" id=\"solution-8\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/8/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>import unittest\nfrom app.models import User</p>\n<p>class UserModelTestCase(unittest.TestCase):\n def test_password_setter(self):\n u = User(password = 'cat')\n self.assertTrue(u.password_hash is not None)</p>\n<div class=\"highlight\"><pre><code>def test_no_password_getter(self):\n u = User(password = 'cat')\n with self.assertRaises(AttributeError):\n u.password\n\ndef test_password_verification(self):\n u = User(password = 'cat')\n self.assertTrue(u.verify_password('cat'))\n self.assertFalse(u.verify_password('dog'))\n\ndef test_password_salts_are_random(self):\n u = User(password='cat')\n u2 = User(password='cat')\n self.assertTrue(u.password_hash != u2.password_hash)</code></pre></div>\n </div>\n</div><p>Content of app/auth/__init.py:</p>\n<div class=\"solution\" id=\"solution-9\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/9/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>from flask import Blueprint</p>\n<p>auth = Blueprint('auth', <strong>name</strong>)</p>\n<p>from . import views</p>\n </div>\n</div><p>Content of app/auth/views.py:</p>\n<div class=\"solution\" id=\"solution-10\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/10/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>from flask import render_template\nfrom . import auth</p>\n<p>@auth.route('/login')\ndef login():\n return render_template('auth/login.html')</p>\n </div>\n</div><p>Content of app/auth/forms.py:</p>\n<div class=\"solution\" id=\"solution-11\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/11/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <p>from flask_wtf import FlaskForm\nfrom wtforms import StringField, PasswordField, BooleanField, SubmitField\nfrom wtforms.validators import DataRequired, Length, Email</p>\n<p>class LoginForm(FlaskForm):\n email = StringField('Email', validators=[DataRequired(), Length(1, 64),\n Email()])\n password = PasswordField('Password', validators=[DataRequired()])\n remember_me = BooleanField('Keep me logged in')\n submit = SubmitField('Log In')</p>\n </div>\n</div><p>Content of app/templates/base.html:</p>\n<div class=\"solution\" id=\"solution-12\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/12/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"x\"><ul class="nav navbar-nav navbar-right"></span>\n<span class=\"x\"> </span><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">current_user.is_authenticated</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"x\"> <li><a href="</span><span class=\"cp\">{{</span> <span class=\"nv\">url_for</span><span class=\"o\">(</span><span class=\"s1\">'auth.logout'</span><span class=\"o\">)</span> <span class=\"cp\">}}</span><span class=\"x\">">Log Out</a></li></span>\n<span class=\"x\"> </span><span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"x\"> <li><a href="</span><span class=\"cp\">{{</span> <span class=\"nv\">url_for</span><span class=\"o\">(</span><span class=\"s1\">'auth.login'</span><span class=\"o\">)</span> <span class=\"cp\">}}</span><span class=\"x\">">Log In</a></li></span>\n<span class=\"x\"> </span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"x\"></ul></span>\n</pre></div>\n </div>\n</div><p>Content of apps/templates/auth/login.html</p>\n<div class=\"solution\" id=\"solution-13\">\n <h3>Řešení</h3>\n <div class=\"solution-cover\">\n <a href=\"/2019/tieto-ostrava-jaro/beginners/tieto-final-assignment/index/solutions/13/\"><span class=\"link-text\">Ukázat řešení</span></a>\n </div>\n <div class=\"solution-body\" aria-hidden=\"true\">\n <div class=\"highlight\"><pre><span></span><span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">"base.html"</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"cp\">{%</span> <span class=\"k\">import</span> <span class=\"s2\">"bootstrap/wtf.html"</span> <span class=\"k\">as</span> <span class=\"nv\">wtf</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">title</span> <span class=\"cp\">%}</span><span class=\"x\">Flasky - Login</span><span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">page_content</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"x\"><div class="page-header"></span>\n<span class=\"x\"> <h1>Login</h1></span>\n<span class=\"x\"></div></span>\n<span class=\"x\"><div class="col-md-4"></span>\n<span class=\"x\"> </span><span class=\"cp\">{{</span> <span class=\"nv\">wtf.quick_form</span><span class=\"o\">(</span><span class=\"nv\">form</span><span class=\"o\">)</span> <span class=\"cp\">}}</span><span class=\"x\"></span>\n<span class=\"x\"></div></span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">endfilter</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">filter</span> <span class=\"nf\">solution</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">"base.html"</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">title</span> <span class=\"cp\">%}</span><span class=\"x\">Flasky</span><span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n\n<span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">page_content</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n<span class=\"x\"><div class="page-header"></span>\n<span class=\"x\"> <h1>Hello, </span><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">current_user.is_authenticated</span> <span class=\"cp\">%}{{</span> <span class=\"nv\">current_user.username</span> <span class=\"cp\">}}{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span><span class=\"x\">Stranger</span><span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span><span class=\"x\">!</h1></span>\n<span class=\"x\"></div></span>\n<span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span><span class=\"x\"></span>\n</pre></div>\n </div>\n</div><ol>\n<li>Create test case for first function (route)</li>\n<li>Create first function</li>\n<li>Create basic application that will do following:<ul>\n<li>Allow users to log-in</li>\n<li>Use Templates</li>\n<li>Use Web Forms</li>\n<li>Use SQLite or PostreSQL/MySQL</li>\n<li>Error Handling</li>\n<li>Use Bootstrap 4</li>\n<li>Use logging to the console and log file</li>\n<li>Email Support (sending notification about new sport activity)</li>\n<li>Allow user to add new kind of sport (like running)</li>\n<li>Allow user to add new activity and assign it to the sport type</li>\n<li>Display last ten activities on Dashboard</li>\n</ul>\n</li>\n</ol>\n\n\n " } } }