Skip to content

c17 sea turtles - jae #111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: gunicorn 'app:create_app()'
22 changes: 19 additions & 3 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
import os
from dotenv import load_dotenv
import os
from flask_cors import CORS


db = SQLAlchemy()
Expand All @@ -12,6 +14,10 @@

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

app.config['CORS_HEADERS'] = 'Content-Type'


app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

if test_config is None:
Expand All @@ -22,13 +28,23 @@ def create_app(test_config=None):
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
"SQLALCHEMY_TEST_DATABASE_URI")

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

# Import models here for Alembic setup
from app.models.task import Task
from app.models.goal import Goal

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

from .routes import task_bp, goal_bp
app.register_blueprint(task_bp)
app.register_blueprint(goal_bp)
# app.register_blueprint(main_bp)

# Register Blueprints here


# Register Blueprints here
CORS(app)
return app
12 changes: 12 additions & 0 deletions app/helper_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@


from flask import jsonify, abort, make_response

def error_message(message, status_code):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

For the name of this file, the file doesn't contain routes for something called a helper, it contains helpers for routes, so I would name this route_helpers.py

abort(make_response(jsonify(dict(details=message)), status_code))




# validate record
# pass in the actual class in our function, to use for both models !
16 changes: 15 additions & 1 deletion app/models/goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,18 @@


class Goal(db.Model):
goal_id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String, nullable=False)
tasks = db.relationship('Task', backref='goal', lazy=True)


def to_dict(self):
return dict(
id=self.id,
title=self.title)




## ONE TO MANY RELATIONSHIP
# GOALS HAVE MANY TASKS
71 changes: 69 additions & 2 deletions app/models/task.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,72 @@
from app import db


class Task(db.Model):
task_id = db.Column(db.Integer, primary_key=True)
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String, nullable=False)
description = db.Column(db.String, nullable=False)
is_complete = db.Column(db.Boolean, default=False)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider not making an actual is_complete column. We can calculate whether the task is complete or not based on the completed_at timestamp. If we store redundant data, we run the risk of the two pieces of data getting out of sync (say we update one but forget to update the other).

completed_at = db.Column(db.DateTime, default=None)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For nullable columns, their default value is NULL (None), so we don't need to specify this here.

goal_id = db.Column(db.Integer, db.ForeignKey('goal.id'))
# goal = db.relationship ("Goal", backref='tasks')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we don't need this relationship since we have the backref over in goal.py.




def to_dict(self):
task_dict = dict(
# goal_id=self.goal_id
id=self.id,
title=self.title,
description=self.description,
is_complete= self.is_complete

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line you commented out would be a big help here!

            is_complete= True if self.completed_at else False

would allow us to get rid of the column, and the later completed_at check.

)

# True if self.completed_at else False

if self.completed_at:
task_dict['is_complete'] = True

if self.goal_id:
task_dict['goal_id'] = self.goal_id
Comment on lines +28 to +29

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice way to add the goal id for tasks that are part of a goal.


return task_dict




@classmethod
def from_dict(cls, data_dict):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 But try to clean up the code that's not being used.


return cls(
title=data_dict["title"],
description=data_dict["description"]
# is_complete=data_dict["is_complete"],
# completed_at=data_dict["completed_at"]
# is_complete=data_dict["is_complete"],

)

def replace_details(self, data_dict):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Nice helper to update the task details, including the optional completed_at. But we can think about getting rid of the is_complete.

Also consider leaving off the call to convert the task to a dictionary. There's no real relationship between updating a task, and converting it to a dictionary. One is business logic, and the other is for sending a result back to the an API caller.

self.title=data_dict["title"]
self.description=data_dict["description"]

if "completed_at" in data_dict:
self.completed_at=data_dict["completed_at"]
self.is_complete= True

return self.to_dict()



# completed_at : default null (none)

# is_complete(db.relationship)


# when we care a new task, completed_att should be NULL (NONE)







Loading