Skip to content

Commit

Permalink
Merge branch 'master' into python-array
Browse files Browse the repository at this point in the history
  • Loading branch information
KateFinegan authored Dec 13, 2023
2 parents 75f97ef + fe67c99 commit 3db8403
Show file tree
Hide file tree
Showing 39 changed files with 962 additions and 0 deletions.
84 changes: 84 additions & 0 deletions flask-database/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Flask Series: Sample Project

This repository contains the code for the `board` Flask sample project.

## Setup

You can run the provided example project on your local machine by following the steps outlined below.

Create a new virtual environment:

```bash
python3 -m venv venv/
```

Activate the virtual environment:

```bash
source ./venv/bin/activate
```

Navigate to the folder for the step that you're currently on.

Install the dependencies for this project if you haven't installed them yet:

```bash
(venv) $ python -m pip install -r requirements.txt
```

### Environment Variables

This project works with environment variables that the application expects in a `.env` file inside the root directory of your project.

Create a `.env` file with this content:

```
FLASK_SECRET_KEY="mysecretkey"
FLASK_DATABASE="board.sqlite"
```

You can add your own content there, but you must define it before running the Flask application.

#### Secret Key

If you want to deploy your Flask app later, then it's a good idea to generate a proper secret key.

If you need to create cryptographically sound data like a Flask secret key, then you can use Python's [`secrets`](https://docs.python.org/3/library/secrets.html) module:

```pycon
>>> import secrets
>>> secrets.token_hex()
'2e9ac41b1e0b66a8d93d66400e2300c4b4c2953f'
```

The `.token_hex()` method returns a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) string containing random numbers and letters from `0` to `9` and `a` to `f`. Use the value that `secrets.token_hex()` outputs for you and add it to your Flask project's `.env` file:

```
# .env
FLASK_SECRET_KEY="2e9ac41b1e0b66a8d93d66400e2300c4b4c2953f"
FLASK_DATABASE="board.sqlite"
```

To avoid saving the secret key directly in your code, it may be a good idea to work with [environment variables](https://12factor.net/config). You can learn more about that in the Flask documentation on [configuration handling](https://flask.palletsprojects.com/en/2.3.x/config/).

### Database

To initialize the database, run this command:

```bash
(venv) $ python -m flask --app board init-db
```

If you used the content for the `.env` file from above, then you can find a `board.sqlite` database in the root directory of your project.

## Development Server

To run the Flask development server, enter this command in your terminal while being in the root directory of your project:

```bash
(venv) $ python -m flask --app board run --debug
```

Now you can navigate to the address that's shown in the output when you start the server. Commonly, that's `http://localhost:5000/`.
20 changes: 20 additions & 0 deletions flask-database/board/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import os
from dotenv import load_dotenv
from flask import Flask

from board import pages, database, posts

load_dotenv()


def create_app():
app = Flask(__name__)
app.config.from_prefixed_env()

database.init_app(app)

app.register_blueprint(pages.bp)
app.register_blueprint(posts.bp)
print(f"Current Environment: {os.getenv('ENVIRONMENT')}")
print(f"Using Database: {app.config.get('DATABASE')}")
return app
36 changes: 36 additions & 0 deletions flask-database/board/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import sqlite3
import click
from flask import current_app, g


def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)


@click.command("init-db")
def init_db_command():
db = get_db()

with current_app.open_resource("schema.sql") as f:
db.executescript(f.read().decode("utf8"))

click.echo("You successfully initialized the database!")


def get_db():
if "db" not in g:
g.db = sqlite3.connect(
current_app.config["DATABASE"],
detect_types=sqlite3.PARSE_DECLTYPES,
)
g.db.row_factory = sqlite3.Row

return g.db


def close_db(e=None):
db = g.pop("db", None)

if db is not None:
db.close()
13 changes: 13 additions & 0 deletions flask-database/board/pages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from flask import Blueprint, render_template

bp = Blueprint("pages", __name__)


@bp.route("/")
def home():
return render_template("pages/home.html")


@bp.route("/about")
def about():
return render_template("pages/about.html")
38 changes: 38 additions & 0 deletions flask-database/board/posts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from flask import (
Blueprint,
redirect,
render_template,
request,
url_for,
)

from board.database import get_db

bp = Blueprint("posts", __name__)


@bp.route("/create", methods=("GET", "POST"))
def create():
if request.method == "POST":
author = request.form["author"] or "Anonymous"
message = request.form["message"]

if message:
db = get_db()
db.execute(
"INSERT INTO post (author, message) VALUES (?, ?)",
(author, message),
)
db.commit()
return redirect(url_for("posts.posts"))

return render_template("posts/create.html")


@bp.route("/posts")
def posts():
db = get_db()
posts = db.execute(
"SELECT author, message, created FROM post ORDER BY created DESC"
).fetchall()
return render_template("posts/posts.html", posts=posts)
8 changes: 8 additions & 0 deletions flask-database/board/schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
DROP TABLE IF EXISTS post;

CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
author TEXT NOT NULL,
message TEXT NOT NULL
);
86 changes: 86 additions & 0 deletions flask-database/board/static/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
* {
box-sizing: border-box;
}

body {
font-family: sans-serif;
font-size: 20px;
margin: 0 auto;
text-align: center;
}

a,
a:visited {
color: #007BFF;
}

a:hover {
color: #0056b3;
}

nav ul {
list-style-type: none;
padding: 0;
}

nav ul li {
display: inline;
margin: 0 5px;
}

main {
width: 80%;
margin: 0 auto;
}

article, form {
text-align: left;
min-width: 200px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0px 0px 10px #ccc;
vertical-align: top;
}

aside {
color: #ccc;
text-align: right;
}

form {
display: flex;
flex-direction: column;
margin-top: 20px;
}

.form-group {
margin-bottom: 20px;
}

.form-control {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
font-size: 1em;
}

.submit-btn {
background-color: #007BFF;
color: #fff;
border: none;
border-radius: 4px;
padding: 10px 20px;
cursor: pointer;
font-size: 1em;
}

.submit-btn:hover {
background-color: #0056b3;
}

.message {
font-size: 2.5em;
font-family: serif;
margin: 0;
padding: 0;
}
8 changes: 8 additions & 0 deletions flask-database/board/templates/_navigation.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<nav>
<ul>
<li><a href="{{ url_for('pages.home') }}">Home</a></li>
<li><a href="{{ url_for('pages.about') }}">About</a></li>
<li><a href="{{ url_for('posts.posts') }}">All Posts</a></li>
<li><a href="{{ url_for('posts.create') }}">Add Post</a></li>
</ul>
</nav>
19 changes: 19 additions & 0 deletions flask-database/board/templates/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Message Board - {% block title %}{% endblock title %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<h1>Message Board</h1>
{% include("_navigation.html") %}
<section>
<header>
{% block header %}{% endblock header %}
</header>
<main>
{% block content %}<p>No messages.</p>{% endblock content %}
<main>
</section>
</body>
</html>
9 changes: 9 additions & 0 deletions flask-database/board/templates/pages/about.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'base.html' %}

{% block header %}
<h2>{% block title %}About{% endblock title %}</h2>
{% endblock header %}

{% block content %}
<p>This is a message board for friendly messages.</p>
{% endblock content %}
9 changes: 9 additions & 0 deletions flask-database/board/templates/pages/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends 'base.html' %}

{% block header %}
<h2>{% block title %}Home{% endblock title %}</h2>
{% endblock header %}

{% block content %}
<p>Learn more about this project by visiting the <a href="{{ url_for('pages.about') }}">About page</a>.</p>
{% endblock content %}
21 changes: 21 additions & 0 deletions flask-database/board/templates/posts/create.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% extends 'base.html' %}

{% block header %}
<h2>{% block title %}Add Post{% endblock title %}</h2>
{% endblock header %}

{% block content %}
<form method="post">
<div class="form-group">
<label for="author">Your Name</label>
<input type="text" name="author" id="author" value="{{ request.form['author'] }}" class="form-control">
</div>
<div class="form-group">
<label for="message">Your Message</label>
<textarea name="message" id="message" class="form-control">{{ request.form['message'] }}</textarea>
</div>
<div class="form-group">
<input type="submit" value="Post Message" class="submit-btn">
</div>
</form>
{% endblock content %}
14 changes: 14 additions & 0 deletions flask-database/board/templates/posts/posts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends 'base.html' %}

{% block header %}
<h2>{% block title %}Posts{% endblock title %}</h2>
{% endblock header %}

{% block content %}
{% for post in posts %}
<article>
<p class="message">{{ post["message"] }}<p>
<aside>Posted by {{ post["author"] }} on {{ post["created"].strftime("%b %d, %Y at %-I:%M%p") }}</aside>
</article>
{% endfor %}
{% endblock content %}
3 changes: 3 additions & 0 deletions flask-database/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
click==8.1.7
Flask==3.0.0
python-dotenv==1.0.0
Loading

0 comments on commit 3db8403

Please sign in to comment.