-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into python-magic-methods
- Loading branch information
Showing
45 changed files
with
1,064 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.