Skip to content

Commit 809bebb

Browse files
committed
first attempt to integrate backend and front-end
1 parent 466f84d commit 809bebb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2434
-2728
lines changed

.gitignore

+10-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Thumbs.db
5252
# ignore node/grunt dependency directories
5353
node_modules/
5454

55+
# webpack output
56+
dist/*
5557
public/
5658

5759
# ignore the dist directory were our bundle files are going to be
@@ -60,4 +62,11 @@ public/
6062
!.htaccess
6163
!.eslintrc
6264
!.env.example
63-
.now
65+
.now
66+
67+
# backend stuff
68+
.venv
69+
database.database
70+
database.db
71+
diagram.png
72+
__pycache__/

.gitpod.yml

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
ports:
22
- port: 3000
3-
onOpen: open-browser
3+
onOpen: open-preview
4+
- port: 3306
5+
onOpen: ignore
46
tasks:
7+
- init: >
8+
cp .env.example .env;
9+
pipenv install;
10+
mysql -u root -e "CREATE DATABASE example";
11+
pipenv run init;
12+
pipenv run migrate;
13+
pipenv run upgrade;
514
- init: >
615
npm i now -g &&
716
npm install &&
817
cp .env.example .env
18+
openMode: split-right

.htaccess

-11
This file was deleted.

CHANGELOG.md

-4
This file was deleted.

Pipfile

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[[source]]
2+
name = "pypi"
3+
url = "https://pypi.org/simple"
4+
verify_ssl = true
5+
6+
[dev-packages]
7+
8+
[packages]
9+
flask = "*"
10+
sqlalchemy = "*"
11+
flask-sqlalchemy = "*"
12+
flask-migrate = "*"
13+
flask-swagger = "*"
14+
psycopg2-binary = "*"
15+
python-dotenv = "*"
16+
mysql-connector-python = "*"
17+
flask-cors = "*"
18+
gunicorn = "*"
19+
mysqlclient = "*"
20+
21+
[requires]
22+
python_version = "3.8"
23+
24+
[scripts]
25+
start="flask run -p 3000 -h 0.0.0.0"
26+
init="flask db init"
27+
migrate="flask db migrate"
28+
upgrade="flask db upgrade"
29+
deploy="echo 'Please follow this 3 steps to deploy: https://github.com/4GeeksAcademy/flask-rest-hello/blob/master/README.md#deploy-your-website-to-heroku' "

Pipfile.lock

+332
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Procfile

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
release: pipenv run upgrade
2+
web: gunicorn wsgi --chdir ./src/

deploy-to-github.js

-59
This file was deleted.

docs/CHANGE_LOG.md

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# CHANGE LOG
2+
3+
Here we are tracking the previous and upcoming changes (roadmap), pull request this file or open an issue if you have any suggestions for the next version of the boilerplate.
4+
5+
## Roadmap v2.0
6+
7+
- [ ] Update documentation with more examples
8+
9+
### August 9th, 2019
10+
- [x] Removed eralchemy from the Pipfile because its compatibility with Apply and PC computers its not clear. There is now way to create a database diagra.png anymore.
11+
- [x] Added this changelog file to keep track of changes on the boilerplate.
12+
- [x] Added documentation for [data validations](https://github.com/4GeeksAcademy/flask-rest-hello/blob/master/docs/DATA_VALIDATIONS.md)
13+
- [x] Added documentation for [SQL Alchemy operations](https://github.com/4GeeksAcademy/flask-rest-hello/edit/master/docs/MYSQL.md).
14+
15+
### Sep 16th, 2019
16+
- [x] Added debuging functionality

docs/DATABASE.md

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Creating and/or Accessing the MySQL Database
2+
3+
1. Log in to mysql terminal:
4+
```sh
5+
$ mysql
6+
```
7+
2. Once inside, check if you have the database already created:
8+
```sql
9+
SHOW databases;
10+
```
11+
3. If you don't see the example database create it by typing:
12+
```sql
13+
CREATE DATABASE example;
14+
```
15+
Note: Make sure to update the `DB_CONNECTION_STRING` on the `.env` file with the correct database name.
16+
17+
3. If your database is already created, get inside of it by typing:
18+
```sql
19+
USE example;
20+
```
21+
4. Now you can type any SQL command you like, for example:
22+
```sql
23+
SHOW TABLES;
24+
```
25+
Note: type `exit;` to quit.
26+
27+
28+
# Querying data using Python and SQL Alchemy (SELECT)
29+
30+
Assuming you have a Person object in your models.py file.
31+
32+
```py
33+
# get all the people
34+
people_query = Person.query.all()
35+
36+
# get only the ones named "Joe"
37+
people_query = Person.query.filter_by(name='Joe')
38+
39+
# map the results and your list of people inside of the all_people variable
40+
all_people = list(map(lambda x: x.serialize(), people_query))
41+
42+
# get just one person
43+
user1 = Person.query.get(person_id)
44+
```
45+
46+
## Inserting data
47+
48+
Assuming you have a Person object in your models.py file.
49+
50+
```py
51+
user1 = Person(username="my_super_username", email="[email protected]")
52+
db.session.add(user1)
53+
db.session.commit()
54+
```
55+
56+
### Updating data
57+
58+
```py
59+
user1 = Person.query.get(person_id)
60+
if user1 is None:
61+
raise APIException('User not found', status_code=404)
62+
63+
if "username" in body:
64+
user1.username = body["username"]
65+
if "email" in body:
66+
user1.email = body["email"]
67+
db.session.commit()
68+
```
69+
70+
### Delete data
71+
72+
```py
73+
user1 = Person.query.get(person_id)
74+
if user1 is None:
75+
raise APIException('User not found', status_code=404)
76+
db.session.delete(user1)
77+
db.session.commit()
78+
```
79+
80+
## ONE to MANY relationship
81+
A one to many relationship places a foreign key on the child table referencing the parent.
82+
Relationship() is then specified on the parent, as referencing a collection of items represented by the child:
83+
84+
```py
85+
class Parent(db.Model):
86+
id = db.Column(db.Integer, primary_key=True)
87+
name = db.Column(db.String(80), nullable=False)
88+
children = db.relationship('Child', lazy=True)
89+
90+
def __repr__(self):
91+
return f'<Parent {self.name}>'
92+
93+
def serialize(self):
94+
return {
95+
"id": self.id,
96+
"name": self.name,
97+
"children": list(map(lambda x: x.serialize(), self.children))
98+
}
99+
100+
class Child(db.Model):
101+
id = db.Column(db.Integer, primary_key=True)
102+
name = db.Column(db.String(80), nullable=False)
103+
parent_id = db.Column(db.Integer, db.ForeignKey("Parent.id"))
104+
105+
def __repr__(self):
106+
return '<Child {self.name}>
107+
108+
def serialize(self):
109+
return {
110+
"id": self.id,
111+
"name": self.name
112+
}
113+
```
114+
115+
## MANY to MANY relationship
116+
Many to Many adds an association table between two classes. The association table is indicated by the secondary argument to relationship(). Usually, the Table uses the MetaData object associated with the declarative base class, so that the ForeignKey directives can locate the remote tables with which to link:
117+
118+
```py
119+
association_table = Table('association', Base.metadata,
120+
Column("sister_id", Integer, ForeignKey("Sister.id")),
121+
Column("brother_id", Integer, ForeignKey("Brother.id"))
122+
)
123+
124+
class Sister(db.Model):
125+
id = db.Column(Integer, primary_key=True)
126+
name = db.Column(String(80), nullable=False)
127+
brothers = relationship("Brother",
128+
secondary=association_table
129+
back_populates="sisters") # this line is so it updates the field when Sister is updated
130+
131+
def __ref__(self):
132+
return f'<Sister {self.name}>'
133+
134+
def serialize(self):
135+
return {
136+
"id": self.id,
137+
"name": self.name,
138+
"brothers": list(map(lambda x: x.serialize(), self.brothers))
139+
}
140+
141+
class Brother(db.Model):
142+
id = db.Column(Integer, primary_key=True)
143+
name = db.Column(String(80), nullable=False)
144+
sisters = relationship("Sister",
145+
secondary=association_table
146+
back_populates="brothers")
147+
148+
def __ref__(self):
149+
return f'<Brother {self.name}>'
150+
151+
def serialize(self):
152+
return {
153+
"id": self.id,
154+
"name": self.name,
155+
"sisters": list(map(lambda x: x.serialize(), self.sisters))
156+
}
157+
```

docs/DATA_VALIDATIONS.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Data Validations
2+
3+
Lets say a request is coming from the client and we need to make sure it contains the right information.
4+
5+
We have to use conditionals to make the validations, if we want to validate the request body we have to retrive it first and then add the condition, like this:
6+
```py
7+
body = request.get_json()
8+
if 'username' not in body:
9+
raise APIException('You need to specify the username', status_code=400)
10+
```
11+
12+
- Its a good practice to raise exeptions because it will stop the code execution.
13+
- Its a good practice to return 400 because that way the client knows it was his mistake and not ours (the server).
14+
15+
### Here is a full example of a POST request to add a new person into a database:
16+
17+
```py
18+
@app.route('/person', methods=['POST'])
19+
def handle_person():
20+
21+
# First we get the payload json
22+
body = request.get_json()
23+
24+
if body is None:
25+
raise APIException("You need to specify the request body as a json object", status_code=400)
26+
if 'username' not in body:
27+
raise APIException('You need to specify the username', status_code=400)
28+
if 'email' not in body:
29+
raise APIException('You need to specify the email', status_code=400)
30+
31+
# at this point, all data has been validated, we can proceed to inster into the bd
32+
user1 = Person(username=body['username'], email=body['email'])
33+
db.session.add(user1)
34+
db.session.commit()
35+
return "ok", 200
36+
```

docs/DEBUGGING.md

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Debugging your application
2+
3+
Gitpod and visual studio come with the same debugging functionality embeded and it is super easy to use!
4+
5+
1. Look for the debugin panel: ![debugging icon](https://raw.githubusercontent.com/4GeeksAcademy/flask-rest-hello/master/docs/assets/debugging_icon.png)
6+
2. Pick `Flask server` as debugging configuration.
7+
3. Add some breakpoints on your code.
8+
4. Press the play button.
9+
5. If the line were you put the breakpoint gets executed your application will froze and show the values of the variables during that particular runtime moment.
10+
11+
![Debugging Gitpod Python](https://raw.githubusercontent.com/4GeeksAcademy/flask-rest-hello/master/docs/assets/debugging.gif)

0 commit comments

Comments
 (0)