Project 4: Movie Watchlist: Render a WTForms form with Jinja and HTML (+174, -0)

routes.py (+13, -0)

From: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/start/movie_library/routes.py

To: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/routes.py

            
            index 3d58ec5..b3bb925 100644
--- a/curriculum/section14/lectures/07_render_wtform_with_jinja_macros/start/movie_library/routes.py
+++ b/curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/routes.py
@@ -5,6 +5,7 @@ from flask import (
     session,
     request,
 )
+from movie_library.forms import MovieForm
 
 
 pages = Blueprint(
@@ -20,6 +21,18 @@ def index():
     )
 
 
+@pages.route("/add", methods=["GET", "POST"])
+def add_movie():
+    form = MovieForm()
+
+    if request.method == "POST":
+        pass
+
+    return render_template(
+        "new_movie.html", title="Movies Watchlist - Add Movie", form=form
+    )
+
+
 @pages.get("/toggle-theme")
 def toggle_theme():
     current_theme = session.get("theme")
        

forms.css (+115, -0)

From: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/static/css/forms.css

To: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/static/css/forms.css

            
            new file mode 100644
index 0000000..c6e3132
--- /dev/null
+++ b/curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/static/css/forms.css
@@ -0,0 +1,115 @@
+.form {
+  margin: 0 auto;
+  max-width: 30rem;
+  border: var(--border);
+  font-size: 1.2rem;
+
+  /* An explicit background is required here, as it's actually transparent by default, and we
+       don't want to see the shadow element behind */
+  background: var(--background-color);
+
+  /* This shadow is separated from the edges by 0.75rem, and shrunk by 0.2rem on the
+  top and bottom. */
+  box-shadow: 0.75rem 0.75rem 0 -0.2rem var(--accent-colour);
+}
+
+.form__container {
+  padding: 2.5rem 1.5rem 1.5rem 1.5rem;
+}
+
+/* The following media queries allow for more padding inside the form as the window
+   size increases */
+@media screen and (min-width: 24.75em) {
+  .form__container {
+    padding-left: 2rem;
+  }
+}
+
+@media screen and (min-width: 30em) {
+  .form__container {
+    padding-left: 2.5rem;
+  }
+}
+
+.form__group {
+  /* Surrounds the label and input fields, placing the label above the input */
+  display: flex;
+  flex-direction: column;
+  margin-bottom: 1.5rem;
+}
+
+.form__label {
+  margin-bottom: 0.5rem;
+}
+
+.form__field {
+  /* Removes the border and the outline highlight when the text field is in focus */
+  outline: none;
+  border: none;
+
+  /* Re-adds a bottom border which will be replaces when the field is in focus. This
+       is going to prevent any jumping when we add the border later */
+  border-bottom: 3px solid #fff;
+
+  /* We have to be explicit about our text fields inheriting font properties */
+  font-size: inherit;
+  font-family: inherit;
+
+  padding: 0.75rem 0.5rem;
+  background: var(--background-color);
+}
+
+/* When the field is in focus, we change the border colour at the bottom to the accent colour */
+.form__field:focus {
+  border-bottom: var(--border);
+}
+
+.form__small {
+  font-size: 0.83rem;
+  color: var(--text-muted);
+}
+
+.form__link {
+  text-decoration: none;
+  color: var(--accent-colour);
+}
+
+.form__link:hover {
+  color: #d05656;
+}
+
+.form__error {
+  margin-top: 0.5rem;
+}
+
+.form__error,
+.form__flash {
+  display: block;
+  padding: 0.5rem;
+  color: var(--text);
+}
+
+.form__error,
+.form__flash--danger {
+  background: var(--accent-colour);
+}
+
+.form__flash {
+  margin: 0.5rem;
+}
+
+.form__flash--success {
+  background: var(--accent-colour-2);
+}
+
+/* Styles specific to the form buttons */
+.button--form {
+  margin: 2rem 0 0 auto;
+  padding: 0.75rem 3rem;
+  border: none;
+  background: var(--background-color);
+}
+
+.button--form:hover {
+  background: var(--background-color-hover);
+}
        

fields.jinja2 (+22, -0)

From: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/macros/fields.jinja2

To: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/macros/fields.jinja2

            
            new file mode 100644
index 0000000..e96b72a
--- /dev/null
+++ b/curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/macros/fields.jinja2
@@ -0,0 +1,22 @@
+{% macro render_text_field(field) %}
+<div class="form__group">
+    {{ field.label(class_="form__label") }}
+    {{ field(class_="form__field")}}
+
+    {%- for error in field.errors %}
+        <span class="form__error">{{ error }}</span>
+    {% endfor %}
+</div>
+{% endmacro %}
+
+
+{% macro render_area_field(field) %}
+<div class="form__group">
+    {{ field.label(class_="form__label") }}
+    {{ field(rows=4, class_="form__field", style="resize: none") }}
+
+    {%- for error in field.errors %}
+        <span class="form__error">{{ error }}</span>
+    {% endfor %}
+</div>
+{% endmacro %}
        

new_movie.html (+24, -0)

From: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/new_movie.html

To: curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/new_movie.html

            
            new file mode 100644
index 0000000..87514c2
--- /dev/null
+++ b/curriculum/section14/lectures/07_render_wtform_with_jinja_macros/end/movie_library/templates/new_movie.html
@@ -0,0 +1,24 @@
+{% 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="add_movie" method="post" novalidate class="form">
+        <div class="form__container">
+            {{ form.hidden_tag() }}
+            {{ render_text_field(form.title) }}
+            {{ render_text_field(form.director) }}
+            {{ render_text_field(form.year) }}
+    
+            <div>
+                {{ form.submit(class_="button button--form") }}
+            </div>
+        </div>
+    </form>
+
+{% endblock %}