Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
fb05342
add app folder and planet class in routes.py
wich229 Dec 14, 2022
2e959f8
added get_all_planets endpoint
wich229 Dec 14, 2022
f834236
create endpoint for getting one planet by id
mckay1818 Dec 15, 2022
721804d
handle invalid planet id requests
mckay1818 Dec 15, 2022
d9f4c75
added models folder, hooked up db
mckay1818 Dec 20, 2022
1ff7357
define planet model
mckay1818 Dec 20, 2022
fc8a4f3
add endpoint to create new planet
mckay1818 Dec 20, 2022
dc7b983
debugging create planet endpoint
mckay1818 Dec 20, 2022
33574d8
added new get all planets endpoint
mckay1818 Dec 20, 2022
e5848ef
added planet id validation and endpoint to replace data for 1 planet
mckay1818 Dec 21, 2022
3ea2a57
add endpoint for reading 1 planet by id
mckay1818 Dec 21, 2022
897f771
add endpoint to delete one planet by id
mckay1818 Dec 21, 2022
8907abe
handle sorting query params
mckay1818 Dec 22, 2022
975cdab
handle query params for filtering by name
mckay1818 Dec 22, 2022
9f66c23
created envars for testing and development environments
mckay1818 Jan 3, 2023
5a398c8
create test folder
mckay1818 Jan 3, 2023
927e217
confirm conftest.py and test_routes.py test and run.
wich229 Jan 3, 2023
4744c13
add tests for POST, PUT, DELETE requests
mckay1818 Jan 3, 2023
0831401
add app folder and planet class in routes.py
wich229 Jan 3, 2023
01a68b2
Merge branch 'main' into mckay_tests
wich229 Jan 4, 2023
3a1c9a9
Merge pull request #1 from mckay1818/mckay_tests
wich229 Jan 4, 2023
f52c79d
change respose body to josnify.
wich229 Jan 4, 2023
6e543a4
refactored Planet class to include to_dict method
mckay1818 Jan 4, 2023
b3b8922
add from_dict class method to Planet model
mckay1818 Jan 4, 2023
8888756
refactored validate_planet fn to more general validate_model fn
mckay1818 Jan 4, 2023
4a70136
add test_models file
mckay1818 Jan 4, 2023
bc15081
from_dict pass test model
wich229 Jan 4, 2023
8a9b795
add from_dict refactor in planet_routes.py
wich229 Jan 4, 2023
80face3
add validate_model and test
wich229 Jan 4, 2023
ec94bf5
fix typo
wich229 Jan 4, 2023
94e9e7d
add Moon model
mckay1818 Jan 5, 2023
4aed045
create and register Moon blueprint
mckay1818 Jan 5, 2023
8ced999
update to_dict
mckay1818 Jan 5, 2023
7e7e296
create to_dict instance method and from_dict class me
mckay1818 Jan 5, 2023
3b76411
add nested roustes in planet_routes.py, routes_helper.py and modified…
wich229 Jan 5, 2023
73aa8ce
refactored nested routes
mckay1818 Jan 6, 2023
c278dec
Merge pull request #2 from mckay1818/nested-routes-refactor
wich229 Jan 6, 2023
a6454f9
add routes for Moons
mckay1818 Jan 6, 2023
3ac94be
Merge branch 'main' of https://github.com/mckay1818/solar-system-api
mckay1818 Jan 6, 2023
7423f6d
routes and models adjustments
wich229 Jan 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added Procfile
Empty file.
27 changes: 27 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from dotenv import load_dotenv
import os

db = SQLAlchemy()
migrate = Migrate()
load_dotenv()

def create_app(test_config=None):
app = Flask(__name__)

app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

if not test_config:
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("SQLALCHEMY_DATABASE_URI")

else:
app.config["TESTING"] = True
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get("SQLALCHEMY_TEST_DATABASE_URI")

db.init_app(app)
migrate.init_app(app, db)

from app.models.planet import Planet
from app.models.moon import Moon

from .routes.planet_routes import planets_bp
from .routes.moon_routes import moons_bp
app.register_blueprint(planets_bp)
app.register_blueprint(moons_bp)

return app
Empty file added app/models/__init__.py
Empty file.
31 changes: 31 additions & 0 deletions app/models/moon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#get db access
from app import db

class Moon(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String, nullable=False)
size = db.Column(db.Integer, nullable=False)
description = db.Column(db.String, nullable=False)
planet_id = db.Column(db.Integer, db.ForeignKey("planet.id"))
planet = db.relationship("Planet", back_populates="moons")

def to_dict(self):
moon_dict = {
"id": self.id,
"name": self.name,
"size": self.size,
"description": self.description,
"planet_id": self.planet_id
}

return moon_dict

@classmethod
def from_dict(cls, moon_data):
new_moon = Moon(
name = moon_data["name"],
size = moon_data["size"],
description = moon_data["description"],
planet = moon_data["planet"]
)
return new_moon
29 changes: 29 additions & 0 deletions app/models/planet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#get db access
from app import db

class Planet(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String, nullable=False)
description = db.Column(db.String, nullable=False)
color = db.Column(db.String, nullable=False)
moons = db.relationship("Moon", back_populates="planet")

def to_dict(self):
return {
"id": self.id,
"name": self.name,
"description": self.description,
"color": self.color,
"moons": [moon.name for moon in self.moons]
}


@classmethod
def from_dict(cls, planet_data):
new_planet = Planet(
name = planet_data["name"],
description = planet_data["description"],
color = planet_data["color"],
moons = planet_data["moons"]
)
return new_planet
2 changes: 0 additions & 2 deletions app/routes.py

This file was deleted.

38 changes: 38 additions & 0 deletions app/routes/moon_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from flask import Blueprint, jsonify, abort, make_response, request
from app import db
from app.models.planet import Planet
from app.models.moon import Moon
from app.routes.routes_helper import validate_model

moons_bp = Blueprint("moons", __name__, url_prefix="/moons")



@moons_bp.route("", methods=["GET"])
def get_all_moons_name():
moons_query = Moon.query

name_query = request.args.get("name")
if name_query:
moons_query = moons_query.filter(Moon.name.ilike(f"%{name_query}%"))

sort_query = request.args.get("sort")
if sort_query == "asc":
moons_query = moons_query.order_by(Moon.name.asc())
if sort_query == "desc":
moons_query = moons_query.order_by(Moon.name.desc())

moons = moons_query.all()

moons_response = []
for moon in moons:
moons_response.append(moon.to_dict()["name"])

return jsonify(moons_response)



@moons_bp.route("/<moon_id>", methods=["GET"])
def get_one_moon_by_id(moon_id):
moon = validate_model(Moon, moon_id)
return moon.to_dict()["name"]
126 changes: 126 additions & 0 deletions app/routes/planet_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
from flask import Blueprint, jsonify, abort, make_response, request
from app import db
from app.models.planet import Planet
from app.models.moon import Moon
from app.routes.routes_helper import validate_model

planets_bp = Blueprint("planets", __name__, url_prefix="/planets")

@planets_bp.route("", methods=["POST"])
def create_planet():
planet_data = request.get_json()

new_planet = Planet.from_dict(planet_data)

#add new planet to db
db.session.add(new_planet)
#commit new planet to db
db.session.commit()

return make_response(jsonify(f"Planet {new_planet.name} created."), 201)


@planets_bp.route("", methods=["GET"])
def get_all_planets():
planets_query = Planet.query

name_query = request.args.get("name")
if name_query:
planets_query = planets_query.filter(Planet.name.ilike(f"%{name_query}%"))

sort_query = request.args.get("sort")
if sort_query == "asc":
planets_query = planets_query.order_by(Planet.name.asc())
if sort_query == "desc":
planets_query = planets_query.order_by(Planet.name.desc())

planets = planets_query.all()

planets_response = []
for planet in planets:
planets_response.append(planet.to_dict())

return jsonify(planets_response)

# @planets_bp.route("", methods=["GET"])
# def get_all_planets():
# planets = Planet.query.all()
# planets_response = []

# for planet in planets:
# planets_response.append({
# "id": planet.id,
# "name": planet.name,
# "description": planet.description,
# "color": planet.color
# })

# return jsonify(planets_response)


@planets_bp.route("/<planet_id>", methods=["GET"])
def get_one_planet_by_id(planet_id):
planet = validate_model(Planet, planet_id)
return planet.to_dict()

@planets_bp.route("/<planet_id>", methods=["PUT"])
def update_planet(planet_id):
planet = validate_model(Planet, planet_id)

request_body = request.get_json()

planet.name = request_body["name"]
planet.description = request_body["description"]
planet.color = request_body["color"]

db.session.commit()

return make_response(jsonify(f"Planet #{planet.id} successfully updated."), 200)


@planets_bp.route("/<planet_id>", methods=["DELETE"])
def delete_planet(planet_id):
planet = validate_model(Planet, planet_id)

db.session.delete(planet)
db.session.commit()

return make_response(jsonify(f"Planet #{planet.id} successfully deleted."), 200)


###########################
# nested routes with moon #
###########################

# POST /planets/<planet_id>/moons
@planets_bp.route("/<planet_id>/moons", methods=["POST"])
def create_new_moon_to_planet(planet_id):
planet = validate_model(Planet, planet_id)

moon_data = request.get_json()
# new_moon = Moon.from_dict(moon_data)
# new_moon["planet"] = planet
new_moon = Moon(
name = moon_data["name"],
size = moon_data["size"],
description = moon_data["description"],
planet_id = planet.id
)

db.session.add(new_moon)
db.session.commit()

message = f"Moon {new_moon.name} created and connect with a {new_moon.planet}."
return make_response(jsonify(message),201)


# GET /planets/<planet_id>/moons
@planets_bp.route("/<planet_id>/moons", methods=["GET"])
def get_moons_by_planet_id(planet_id):
planet = validate_model(Planet, planet_id)

moons_response = []
for moon in planet.moons:
moons_response.append(moon.to_dict())

return jsonify(moons_response)
16 changes: 16 additions & 0 deletions app/routes/routes_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from flask import abort, make_response

# helper function
def validate_model(cls, model_id):
try:
model_id = int(model_id)
except:
abort(make_response({"message" : f" {cls.__name__} {model_id} invalid."}, 400))

model = cls.query.get(model_id)

if model:
return model

abort(make_response({"message" : f" {cls.__name__} {model_id} not found."}, 404))

1 change: 1 addition & 0 deletions migrations/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Generic single-database configuration.
45 changes: 45 additions & 0 deletions migrations/alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# A generic, single database configuration.

[alembic]
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s

# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false


# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console
qualname =

[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
Loading