Project 4: Movie Watchlist: Adding user logins to the movie watchlist (+70, -10)

forms.py (+6, -0)

From: curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/forms.py

To: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/forms.py

            
            index a54f8b8..a0b572e 100644
--- a/curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/forms.py
+++ b/curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/forms.py
@@ -17,6 +17,12 @@ from wtforms.validators import (
 )
 
 
+class LoginForm(FlaskForm):
+    email = StringField("Email", validators=[InputRequired(), Email()])
+    password = PasswordField("Password", validators=[InputRequired()])
+    submit = SubmitField("Login")
+
+
 class RegisterForm(FlaskForm):
     email = StringField("Email", validators=[InputRequired(), Email()])
        

routes.py (+27, -2)

From: curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/routes.py

To: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/routes.py

            
            index 10458d2..d615007 100644
--- a/curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/routes.py
+++ b/curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/routes.py
@@ -12,7 +12,7 @@ from flask import (
     url_for,
     request,
 )
-from movie_library.forms import RegisterForm, MovieForm, ExtendedMovieForm
+from movie_library.forms import LoginForm, RegisterForm, MovieForm, ExtendedMovieForm
 from movie_library.models import User, Movie
 from passlib.hash import pbkdf2_sha256
 
@@ -52,13 +52,38 @@ def register():
 
         flash("User registered successfully", "success")
 
-        return redirect(url_for(".index"))
+        return redirect(url_for(".login"))
 
     return render_template(
         "register.html", title="Movies Watchlist - Register", form=form
     )
 
 
+@pages.route("/login", methods=["GET", "POST"])
+def login():
+    if session.get("email"):
+        return redirect(url_for(".index"))
+
+    form = LoginForm()
+
+    if form.validate_on_submit():
+        user_data = current_app.db.user.find_one({"email": form.email.data})
+        if not user_data:
+            flash("Login credentials not correct", category="danger")
+            return redirect(url_for(".login"))
+        user = User(**user_data)
+
+        if user and pbkdf2_sha256.verify(form.password.data, user.password):
+            session["user_id"] = user._id
+            session["email"] = user.email
+
+            return redirect(url_for(".index"))
+
+        flash("Login credentials not correct", category="danger")
+
+    return render_template("login.html", title="Movies Watchlist - Login", form=form)
+
+
 @pages.route("/add", methods=["GET", "POST"])
 def add_movie():
     form = MovieForm()
        

login.html (+34, -0)

From: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/login.html

To: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/login.html

            
            new file mode 100644
index 0000000..ddedfbc
--- /dev/null
+++ b/curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/login.html
@@ -0,0 +1,34 @@
+{% from "macros/fields.html" import render_text_field %}
+
+{% extends "layout.html" %}
+
+{%- block head_content %}
+    <link rel="stylesheet" href="{{ url_for('static', filename='css/forms.css') }}" />
+{% endblock %} 
+
+{% block main_content %}
+
+    <form name="login" method="post" novalidate class="form">
+        {% with messages = get_flashed_messages(with_categories=true) %}
+            {%- for category, message in messages %}
+                <span class="form__flash form__flash--{{category}}"> {{ message }}</span>
+            {% endfor %}
+        {% endwith %}
+
+        <div class="form__container">
+            {{ form.hidden_tag() }}
+    
+            {{ render_text_field(form.email) }}
+            {{ render_text_field(form.password) }}
+    
+            <span class="form__small">
+                Don't have an account? <a href="{{ url_for('pages.register') }}" class="form__link">Register here</a>.
+            </span>
+    
+            <div>
+                {{ form.submit(class_="button button--form") }}
+            </div>
+        </div>
+    </form>
+
+{% endblock %}
        

nav.html (+2, -2)

From: curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/templates/macros/nav.html

To: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/macros/nav.html

            
            index 116ad0a..a7a9ece 100644
--- a/curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/templates/macros/nav.html
+++ b/curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/macros/nav.html
@@ -11,8 +11,8 @@
         <nav class="nav">
             {%- if not email %}
                 <a
-                    href="#"
-                    class="nav__link"
+                    href="{{ url_for('pages.login') }}"
+                    class="nav__link {{ 'nav__link--active' if request.path == url_for('pages.login') }}"
                 >
                     <span class="nav__item">Log in</span>
                 </a>
        

register.html (+1, -6)

From: curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/templates/register.html

To: curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/register.html

            
            index 55c61ad..5e33806 100644
--- a/curriculum/section14/lectures/16_user_login_in_flask_app/start/movie_library/templates/register.html
+++ b/curriculum/section14/lectures/16_user_login_in_flask_app/end/movie_library/templates/register.html
@@ -9,11 +9,6 @@
 {% block main_content %}
 
     <form name="register" method="post" novalidate class="form">
-        {% with messages = get_flashed_messages(with_categories=true) %}
-            {%- for category, message in messages %}
-                <span class="form__flash form__flash--{{category}}"> {{ message }}</span>
-            {% endfor %}
-        {% endwith %}
         <div class="form__container">
             {{ form.hidden_tag() }}
 
@@ -22,7 +17,7 @@
             {{ render_text_field(form.confirm_password) }}
     
             <span class="form__small">
-                Already have an account? <a href="#" class="form__link">Log in here</a>.
+                Already have an account? <a href="{{ url_for('pages.login') }}" class="form__link">Log in here</a>.
             </span>
     
             <div>