Skip to content

Commit 8b6ee05

Browse files
authored
Merge pull request #327 from realpython/build-a-rest-api-frontend-ian
Suggestions for frontend code
2 parents 936ee7b + 94aef6c commit 8b6ee05

File tree

19 files changed

+288
-302
lines changed

19 files changed

+288
-302
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.db
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"printWidth": 79
3+
}

build-a-rest-api-frontend/source_code_final/app.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
from flask import render_template
2+
23
import config
34
from models import Person
45

56
app = config.connex_app
6-
app.add_api("swagger.yml")
7+
app.add_api(config.basedir / "swagger.yml")
78

89

910
@app.route("/")
Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,44 @@
11
from datetime import datetime
2+
23
from config import app, db
3-
from models import Person, Note
4+
from models import Note, Person
45

56
PEOPLE_NOTES = [
67
{
78
"lname": "Fairy",
8-
"fname": "Sugar",
9+
"fname": "Tooth",
910
"notes": [
10-
("Cool, a mini-blogging application!", "2022-01-06 22:17:54"),
11-
("This could be useful", "2022-01-08 22:17:54"),
12-
("Well, sort of useful", "2022-03-06 22:17:54"),
11+
("I brush my teeth after each meal.", "2022-01-06 17:10:24"),
12+
(
13+
"The other day a friend said, I have big teeth.",
14+
"2022-03-05 22:17:54",
15+
),
16+
("Do you pay per gram?", "2022-03-05 22:18:10"),
1317
],
1418
},
1519
{
1620
"lname": "Ruprecht",
1721
"fname": "Knecht",
1822
"notes": [
1923
(
20-
"I'm going to make really profound observations",
21-
"2022-01-07 22:17:54",
24+
"I swear, I'll do better this year.",
25+
"2022-01-01 09:15:03",
2226
),
2327
(
24-
"Maybe they'll be more obvious than I thought",
25-
"2022-02-06 22:17:54",
28+
"Really! Only good deeds from now on!",
29+
"2022-02-06 13:09:21",
2630
),
2731
],
2832
},
2933
{
3034
"lname": "Bunny",
3135
"fname": "Easter",
3236
"notes": [
33-
("Has anyone seen my Easter eggs?", "2022-01-07 22:47:54"),
34-
("I'm really late delivering these!", "2022-04-06 22:17:54"),
37+
(
38+
"Please keep the current inflation rate in mind!",
39+
"2022-01-07 22:47:54",
40+
),
41+
("No need to hide the eggs this time.", "2022-04-06 13:03:17"),
3542
],
3643
},
3744
]
@@ -41,8 +48,7 @@
4148
db.create_all()
4249
for data in PEOPLE_NOTES:
4350
new_person = Person(lname=data.get("lname"), fname=data.get("fname"))
44-
for note in data.get("notes"):
45-
content, timestamp = note
51+
for content, timestamp in data.get("notes", []):
4652
new_person.notes.append(
4753
Note(
4854
content=content,
@@ -52,5 +58,4 @@
5258
)
5359
)
5460
db.session.add(new_person)
55-
5661
db.session.commit()

build-a-rest-api-frontend/source_code_final/config.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import os
1+
import pathlib
2+
23
import connexion
3-
from flask_sqlalchemy import SQLAlchemy
44
from flask_marshmallow import Marshmallow
5+
from flask_sqlalchemy import SQLAlchemy
56

6-
basedir = os.path.abspath(os.path.dirname(__file__))
7+
basedir = pathlib.Path(__file__).parent.resolve()
78
connex_app = connexion.App(__name__, specification_dir=basedir)
89

910
app = connex_app.app
10-
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////" + os.path.join(
11-
basedir, "people.db"
12-
)
11+
app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{basedir / 'people.db'}"
1312
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
1413

1514
db = SQLAlchemy(app)

build-a-rest-api-frontend/source_code_final/models.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from datetime import datetime
2+
23
from marshmallow_sqlalchemy import fields
4+
35
from config import db, ma
46

57

@@ -29,8 +31,9 @@ class Person(db.Model):
2931
timestamp = db.Column(
3032
db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
3133
)
34+
3235
notes = db.relationship(
33-
"Note",
36+
Note,
3437
backref="person",
3538
cascade="all, delete, delete-orphan",
3639
single_parent=True,
@@ -46,3 +49,8 @@ class Meta:
4649
include_relationships = True
4750

4851
notes = fields.Nested(NoteSchema, many=True)
52+
53+
54+
note_schema = NoteSchema()
55+
person_schema = PersonSchema()
56+
people_schema = PersonSchema(many=True)
Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
from flask import make_response, abort
1+
from flask import abort, make_response
22

33
from config import db
4-
from models import (
5-
Note,
6-
NoteSchema,
7-
Person,
8-
)
4+
from models import Note, Person, note_schema
95

106

117
def read_one(note_id):
128
note = Note.query.get(note_id)
139

1410
if note is not None:
15-
note_schema = NoteSchema()
1611
return note_schema.dump(note)
1712
else:
1813
abort(404, f"Note with ID {note_id} not found")
@@ -22,12 +17,11 @@ def update(note_id, note):
2217
existing_note = Note.query.get(note_id)
2318

2419
if existing_note:
25-
schema = NoteSchema()
26-
update_note = schema.load(note, session=db.session)
20+
update_note = note_schema.load(note, session=db.session)
2721
existing_note.content = update_note.content
2822
db.session.merge(existing_note)
2923
db.session.commit()
30-
return schema.dump(existing_note), 201
24+
return note_schema.dump(existing_note), 201
3125
else:
3226
abort(404, f"Note with ID {note_id} not found")
3327

@@ -38,7 +32,7 @@ def delete(note_id):
3832
if existing_note:
3933
db.session.delete(existing_note)
4034
db.session.commit()
41-
return make_response(f"{note_id} successfully deleted", 200)
35+
return make_response(f"{note_id} successfully deleted", 204)
4236
else:
4337
abort(404, f"Note with ID {note_id} not found")
4438

@@ -48,10 +42,9 @@ def create(note):
4842
person = Person.query.get(person_id)
4943

5044
if person:
51-
schema = NoteSchema()
52-
new_note = schema.load(note, session=db.session)
45+
new_note = note_schema.load(note, session=db.session)
5346
person.notes.append(new_note)
5447
db.session.commit()
55-
return schema.dump(new_note), 201
48+
return note_schema.dump(new_note), 201
5649
else:
5750
abort(404, f"Person not found for ID: {person_id}")

build-a-rest-api-frontend/source_code_final/people.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,25 @@
1-
from flask import make_response, abort
1+
from flask import abort, make_response
22

33
from config import db
4-
from models import (
5-
Person,
6-
PersonSchema,
7-
)
4+
from models import Person, people_schema, person_schema
85

96

107
def read_all():
118
people = Person.query.all()
12-
person_schema = PersonSchema(many=True)
13-
return person_schema.dump(people)
9+
return people_schema.dump(people)
1410

1511

1612
def create(person):
17-
schema = PersonSchema()
18-
new_person = schema.load(person, session=db.session)
13+
new_person = person_schema.load(person, session=db.session)
1914
db.session.add(new_person)
2015
db.session.commit()
21-
return schema.dump(new_person), 201
16+
return person_schema.dump(new_person), 201
2217

2318

2419
def read_one(person_id):
2520
person = Person.query.get(person_id)
2621

2722
if person is not None:
28-
person_schema = PersonSchema()
2923
return person_schema.dump(person)
3024
else:
3125
abort(404, f"Person with ID {person_id} not found")
@@ -35,12 +29,11 @@ def update(person_id, person):
3529
existing_person = Person.query.get(person_id)
3630

3731
if existing_person:
38-
schema = PersonSchema()
39-
update_person = schema.load(person, session=db.session)
32+
update_person = person_schema.load(person, session=db.session)
4033
existing_person.fname = update_person.fname
4134
db.session.merge(existing_person)
4235
db.session.commit()
43-
return schema.dump(existing_person), 201
36+
return person_schema.dump(existing_person), 201
4437
else:
4538
abort(404, f"Person with ID {person_id} not found")
4639

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { getData } from "./request.js";
2+
3+
export function showInDebug(data) {
4+
const debugCard = document.querySelector(".debug-card");
5+
if (debugCard) {
6+
let code = debugCard.querySelector("code");
7+
code.innerText = data;
8+
}
9+
}
10+
11+
export class DebugForm {
12+
constructor() {
13+
this.debugCard = document.querySelector(".debug-card");
14+
this.form = this.debugCard.querySelector(".debug-form");
15+
this.clearButton = this.form.querySelector("button[data-action='clear']");
16+
this.clearButton.addEventListener(
17+
"click",
18+
this.handleClearClick.bind(this)
19+
);
20+
this.sendButton = this.form.querySelector("button[data-action='read']");
21+
this.sendButton.addEventListener("click", this.handleSendClick.bind(this));
22+
}
23+
24+
handleClearClick(event) {
25+
event.preventDefault();
26+
let code = this.debugCard.querySelector("code");
27+
code.innerText = "";
28+
}
29+
30+
handleSendClick(event) {
31+
event.preventDefault();
32+
const input = document.querySelector(".debug-card input");
33+
const endpoint = input.value;
34+
getData(endpoint, this.showResponse);
35+
}
36+
37+
showResponse(data) {
38+
const debugCard = document.querySelector(".debug-card");
39+
let code = debugCard.querySelector("code");
40+
code.innerText = data;
41+
}
42+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { People } from "./people.js";
2+
import { Notes } from "./notes.js";
3+
import { DebugForm } from "./debug.js";
4+
5+
function main() {
6+
new People();
7+
new Notes();
8+
const debug = new DebugForm();
9+
debug.showResponse("");
10+
}
11+
12+
main();

0 commit comments

Comments
 (0)