Skip to content
This repository was archived by the owner on Jun 9, 2021. It is now read-only.

Commit 5ea75c7

Browse files
committed
flask-mailroom
1 parent 3817b86 commit 5ea75c7

File tree

9 files changed

+197
-0
lines changed

9 files changed

+197
-0
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
__pycache__/
2+
.idea/
3+
my_database.db
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
web: python main.py
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Flask Mailroom Application
2+
3+
Running at [http://afternoon-reef-51666.herokuapp.com/donations/](http://afternoon-reef-51666.herokuapp.com/donations/).
4+
5+
## Your Task
6+
7+
Your task is to:
8+
9+
1. Add a page with a form for CREATING new donations in the database:
10+
* The page should have a form, with a field for the donor name and a field for the amount of the donation.
11+
* The method of the form should be POST.
12+
* You will need to create a template for this page, inside of the `templates` directory. The template should inherit from `base.jinja2`.
13+
* You should create a route and a handler function inside of `main.py`. The handler function should accept both GET requests and POST requests.
14+
* If the handler receives a GET request, then it should render the template for the donation creation page.
15+
* If the handler receives a POST request (a form submission), then it should attempt to retrieve the name of the donor and the amount of the donation from the form submission. It should retrieve the donor from the database with the indicated name, and create a new donation with the indicated donor and donation amount. Then it should redirect the visitor to the home page.
16+
17+
2. Add navigation elements in `base.jinja2` to the top of both pages. The navigation elements should include links to both the home page and your new donation-creation page.
18+
19+
3. Publish your work to Heroku. If you publish your work to Heroku and then make changes to your application, you will need to publish those changes by commiting your work to your git repository and then executing `git push heroku master`. Make sure that you also `git push origin master` to push your changes to GitHub.
20+
21+
4. Edit the top of this README file, replacing _my_ Heroku link ([http://afternoon-reef-51666.herokuapp.com/donations/](http://afternoon-reef-51666.herokuapp.com/donations/)) with your own Heroku link. If you're unable to get your application running on Heroku, that's no problem. Instead, just write a couple of sentences about where you got hung up.
22+
23+
24+
## Getting Started
25+
26+
I recommend that you begin by forking this repository into your own account, then cloning it to your computer. Then follow the instructions below to run the program. Once you can see the homepage, including a list of donations by Alice, Bob, and Charlie, then you are ready to make your modifications to the program.
27+
28+
## To Run
29+
30+
All commands to be run from inside the repository directory.
31+
```
32+
$ mkvirtualenv flask-mailroom
33+
$ pip install -r requirements.txt
34+
$ python setup.py
35+
$ python main.py
36+
```
37+
38+
Confirm that the application is running on port 6738, and then open your browser to [http://localhost:6738](http://localhost:6738)
39+
40+
## To Publish to Heroku
41+
42+
All commands to be run from inside the repository directory.
43+
```
44+
$ git init # Only necessary if this is not already a git repository
45+
$ heroku create
46+
$ git push heroku master # If you have any changes or files to add, commit them before you push.
47+
$ heroku addons:create heroku-postgresql:hobby-dev
48+
$ heroku run python setup.py
49+
$ heroku open
50+
```
51+
52+
## Taking it Further
53+
54+
Here are some *optional* ways that you can extend your application:
55+
56+
1. Think about what can go wrong with form submission. What would you like to do if a user enters a name that _does not exist_ in the database of donors? One possibility would be to re-display the donation creation form and inject a message describing the error. Another possibility would be to _create_ a new donor with the given name, along with the indicated donation. Implement either solution.
57+
58+
2. Allow all visitors to view the page of donations, but require that users _login_ in order to enter a donation. This would involve new pages, new models, changes to the database `setup.py` file, and the use of a secret key to encode values into the session.
59+
60+
3. Create a page that allows visitors to view all donations from a single donor. You could accomplish this by creating a new page with a form that allows visitors to submit the name of the donor that they would like to see donations for. If the form has been submitted, then the handler function would retrieve that name, find the indicated donor, retrieve all of their donations, and then inject them into the page to be rendered. Ideally, the method of the form would be GET. This extension would include some steps or combinations of code that I may not have demonstrated in the lesson, but that you could probably puzzle out.
61+
62+
If you choose to perform any of these *optional* extensions, then let us know as a comment to your submission!
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import os
2+
import base64
3+
4+
from flask import Flask, render_template, request, redirect, url_for, session
5+
6+
from model import Donation
7+
8+
app = Flask(__name__)
9+
10+
11+
@app.route('/')
12+
def home():
13+
return redirect(url_for('all'))
14+
15+
16+
@app.route('/donations/')
17+
def all():
18+
donations = Donation.select()
19+
return render_template('donations.jinja2', donations=donations)
20+
21+
22+
@app.route('/create/', methods=['GET', 'POST'])
23+
def create():
24+
# If the handler receives a POST request (a form submission),
25+
# then it should attempt to retrieve the name of the donor and
26+
# the amount of the donation from the form submission.
27+
# It should retrieve the donor from the database with the
28+
# indicated name, and create a new donation with the indicated
29+
# donor and donation amount. Then it should redirect
30+
# the visitor to the home page.
31+
if request.method == 'POST':
32+
# Donation.update(value=request.form['value'])\
33+
# .where(Donation.donor == request.form['donor'])\
34+
# .execute()
35+
donation = Donation(value=request.form['value'], donor=request.form['donor'])
36+
donation.save()
37+
return(redirect(url_for('all')))
38+
39+
# If the handler receives a GET request, then it should render
40+
# the template for the donation creation page.
41+
return render_template('create.jinja2')
42+
43+
44+
if __name__ == "__main__":
45+
46+
port = int(os.environ.get("PORT", 6738))
47+
app.run(host='0.0.0.0', port=port)
48+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import os
2+
3+
from peewee import Model, CharField, IntegerField, ForeignKeyField
4+
from playhouse.db_url import connect
5+
6+
db = connect(os.environ.get('DATABASE_URL', 'sqlite:///my_database.db'))
7+
8+
class Donor(Model):
9+
name = CharField(max_length=255, unique=True)
10+
11+
class Meta:
12+
database = db
13+
14+
class Donation(Model):
15+
value = IntegerField()
16+
donor = ForeignKeyField(Donor, backref='donations')
17+
18+
class Meta:
19+
database = db
20+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import random
2+
3+
from model import db, Donor, Donation
4+
5+
db.connect()
6+
7+
# This line will allow you "upgrade" an existing database by
8+
# dropping all existing tables from it.
9+
db.drop_tables([Donor, Donation])
10+
11+
db.create_tables([Donor, Donation])
12+
13+
alice = Donor(name="Alice")
14+
alice.save()
15+
16+
bob = Donor(name="Bob")
17+
bob.save()
18+
19+
charlie = Donor(name="Charlie")
20+
charlie.save()
21+
22+
donors = [alice, bob, charlie]
23+
24+
for x in range(30):
25+
Donation(donor=random.choice(donors), value=random.randint(100, 10000)).save()
26+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<html>
2+
<head>
3+
<title>Mailroom</title>
4+
</head>
5+
<body>
6+
<nav>
7+
<a id="add" href = "{{ url_for('donations') }}">View Donations</a>
8+
<a id="retrieve" href = "{{ url_for('create') }}">Add Donation</a>
9+
</nav>
10+
<h1>Donations</h1>
11+
<h2>{% block subtitle %} {% endblock subtitle %}</h2>
12+
{% block content %} {% endblock content %}
13+
</body>
14+
</html>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{% extends 'base.jinja2' %}
2+
3+
{% block subtitle %}Create a Donation{% endblock subtitle %}
4+
5+
{% block content %}
6+
<form method="POST">
7+
{% if error %}<p>{{ error }}</p>{% endif %}
8+
<label for="donor">Donor Name:</label><input id="donor" type="text" name="donor"><br>
9+
<label for="value">Value:</label><input id="value" type="number" name="value"><br>
10+
<input type="submit" value="Create Donation">
11+
</form>
12+
{% endblock content %}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{% extends 'base.jinja2' %}
2+
3+
{% block subtitle %}Donations{% endblock subtitle %}
4+
5+
{% block content %}
6+
<ul>
7+
{% for donation in donations %}
8+
<li><b>{{ donation.donor.name }}</b>: {{ donation.value }}</li>
9+
{% endfor %}
10+
</ul>
11+
{% endblock content %}

0 commit comments

Comments
 (0)