Skip to content

Instantly share code, notes, and snippets.

@codecademydev
Created December 21, 2022 14:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save codecademydev/3e7515a2ca6f5b665aca39bf27747d3d to your computer and use it in GitHub Desktop.
Save codecademydev/3e7515a2ca6f5b665aca39bf27747d3d to your computer and use it in GitHub Desktop.
Codecademy export
from flask import Flask, render_template, request, redirect, url_for
from locations import Locations
from forms import AddLocationForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'SECRET_PROJECT'
# Note that app.config['SECRET_KEY'] is already set. Remember this is necessary to protect against a Cross-Site Request Forgery attack
visit = Locations()
categories = {"recommended": "Recommended", "tovisit": "Places To Go", "visited": "Visited!!!", }
UP_ACTION = "\u2197"
DEL_ACTION = "X"
@app.route("/<category>", methods=["GET", "POST"])
def locations(category):
locations = visit.get_list_by_category(category)
## Check the request for form data and process by testing requests method attribute
if request.method == "POST":
[(name, action)] = request.form.items()
if action == UP_ACTION:
visit.moveup(name)
elif action == DEL_ACTION:
visit.delete(name)
## Return the main template with variables
return render_template("locations.html", category=category, categories=categories, locations=locations, add_location=AddLocationForm())
@app.route("/add_location", methods=["POST"])
def add_location():
## Validate and collect the form data
add_form = AddLocationForm(csrf_enabled = False)
if add_form.validate_on_submit():
# Remember to use .data extension and reference form to transfer the data!
name=add_form.name.data
description=add_form.description.data
category=add_form.category.data
visit.add(name, description, category)
## Redirect to locations route function
return redirect(url_for("locations", category=category, _external=True, _scheme="https"))
@app.route("/")
def index():
## Redirect to locations route function
return redirect(url_for("locations", category="recommended", _external=True, _scheme="https"))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="../static/styles.css">
<title>Where To Go</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
Petronas Twin Towers World's tallest twin towers recommended
Jalan Alor Street for delicious food recommended
Perdana Botanical Garden Green oasis in the city tovisit
Islamic Arts Museum Large open-plan museum with four levels visited
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, RadioField
from wtforms.validators import DataRequired
class FieldsRequiredForm(FlaskForm):
"""Require radio fields to have content. This works around the bug that WTForms radio fields don't honor the `DataRequired` or `InputRequired` validators.
Note: Provided in forms.py is a new form class, FieldsRequiredForm, that inherits from FlaskForm. This new type of form will allow us to require data for radio button form fields. See programming language below ⬇️ ⬇️ ⬇️
"""
class Meta:
def render_field(self, field, render_kw):
if field.type == "_Option":
render_kw.setdefault("required", True)
return super().render_field(field, render_kw)
categories = [("recommended","Recommended"), ("tovisit", "Places To Go"), ("visited", "Visited!!!")]
## Create Form Here
class AddLocationForm(FieldsRequiredForm):
name = StringField("Location Name", validators=[DataRequired()])
description = TextAreaField("Location Description", validators=[DataRequired()])
category = RadioField("Category", choices=categories)
submit= SubmitField("Add Location")
<!-- extend from "base.html" here -->
{% extends "base.html" %}
{% block content %}
<!-- begin block content here -->
<!-- NOTE! category is not in quotes below! -->
<h1>{{ categories[category] }}</h1> <!-- insert category here -->
<div class="navbar">
<!-- begin for loop here -->
<!-- REMEMBER! items() method returns a "view object" containing the key-value pairs of the dictionary, as tuples in a list. -->
{% for category, label in categories.items() %}
<!-- NOTE! label display value is in double brackets below -->
<a href="{{category}}">{{label}}</a> <!-- set attribute and text here -->
<!-- end for loop here -->
{% endfor %}
</div>
<table>
<colgroup>
<col style="width: 20%">
<col style="width: 70%">
<col style="width: 10%">
</colgroup>
<tbody class="loctable">
<!-- begin for loop here -->
{% for location in locations %}
<tr>
<!-- NOTE! no paraenthesis needed after . name or .description -->
<td class="loc">{{ location.name}}</td> <!-- insert location name here -->
<td class="desc">{{ location.description}}</td><!-- insert location description here -->
<!-- '''NOTE! Double curly delimiters needed for variable assignment and quotes around all attributes but no commas!''' -->
<td class="btns"><input type="submit" name="{{location.name}}" value="Submit">
<!-- start if statement here -->
{% if location.category in ["recommended", "tovisit"] %}
<form method="POST">
<input type="submit" class="up" name="Move Up" value=&#8599;> <!-- set name attribute here -->
<input type="submit" class="del" name="Delete" value="X"> <!-- set name attribute here -->
</form>
<!-- end if statement here -->
{% endif %}
</td>
</tr>
<!-- end for loop here -->
{% endfor %}
</tbody>
</table>
<form class="addform" action="url_for(add_location)" method="POST"> <!-- set action attribute here -->
<!-- call hidden_tag() here -->
<!-- Be sure to:
Use url_for() inside double quotes
Use single quotes for the route function name -->
{{ add_location.hidden_tag() }}
<table>
<colgroup>
<col style="width: 40%">
<col style="width: 40%">
<col style="width: 20%">
</colgroup>
<tbody>
<tr>
<!-- .label attribute gives the field descriptor -->
<td>{{ add_location.name.label }}</td> <!-- insert location name label here -->
<td>{{ add_location.description.label }}</td> <!-- insert location description label here -->
<td>{{ add_location.category.label }}</td> <!-- insert location category label here -->
</tr>
<tr>
<td>{{ add_location.name() }}</td> <!-- insert add_location name here -->
<td>{{ add_location.description() }}</td> <!-- insert add_location description here -->
<td>
<!-- begin for loop here -->
{% for button in add_location.category %}
<!-- Note! use "button" iteration variable's .label to name options -->
<div>{{button()}}{{button.label}}</div> <!-- insert button here --
<!-- end for loop here -->
{% endfor %}
</td>
</tr>
<tr>
<!-- NOTE! NOT using <td class="btns"><input type="submit" ... to create button also NOTE double curly brackets seems to break through comment -->
<td> {{ add_location.submit() }} </td> <!-- insert submit here -->
</tr>
</tbody>
</table>
</form>
<!-- end block content here -->
{% endblock %}
import csv
class Locations:
def __init__(self):
self.locations = []
self.load_data()
def add(self, name, description, category):
if name is not None and description is not None and category is not None:
location = Location(name, description, category)
self.locations.append(location)
def get_index_by_name(self, name):
for i, location in enumerate(self.locations):
if location.name == name:
return i
def get_list_by_category(self, category):
locs = []
for i, location in enumerate(self.locations):
if location.category == category:
locs.append(location)
return locs
def delete(self, name):
i = self.get_index_by_name(name)
self.locations.pop(i)
def moveup(self, name):
i = self.get_index_by_name(name)
if self.locations[i].category == "recommended":
self.locations[i].category = "tovisit"
elif self.locations[i].category == "tovisit":
self.locations[i].category = "visited"
def load_data(self):
with open("data.csv", "r") as csvfile:
locations = csv.reader(csvfile)
for row in locations:
self.add(row[0], row[1], row[2])
def __repr__(self):
for location in self.locations:
print(f'{location.name} - {location.description} - {location.category}')
class Location:
def __init__(self, name, description, category):
self.name = name
self.description = description
self.category = category
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment