-
Notifications
You must be signed in to change notification settings - Fork 71
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
Scissors - Christian C15 #60
base: master
Are you sure you want to change the base?
Changes from all commits
f5a2151
aa3f106
7d98597
7a0c280
b396d17
dcb1519
f7e0bbf
31900b3
b87cf7f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,4 +3,31 @@ | |
|
||
|
||
class Task(db.Model): | ||
task_id = db.Column(db.Integer, primary_key=True) | ||
task_id = db.Column(db.Integer, primary_key=True, autoincrement=True) | ||
title = db.Column(db.String) | ||
description = db.Column(db.String) | ||
completed_at = db.Column(db.DateTime, nullable=True) | ||
goal_id = db.Column(db.Integer, db.ForeignKey('goal.goal_id'), nullable=True) | ||
|
||
|
||
def to_json(self): | ||
|
||
if self.completed_at == None: | ||
is_complete = False | ||
else: | ||
is_complete = True | ||
if self.goal_id: | ||
return { | ||
"id": self.task_id, | ||
"goal_id": self.goal_id, | ||
"title": self.title, | ||
"description": self.description, | ||
"is_complete": is_complete | ||
} | ||
return { | ||
"id": self.task_id, | ||
"title": self.title, | ||
"description": self.description, | ||
"is_complete": is_complete | ||
} | ||
Comment on lines
+19
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notice there is repeated code here. Consider refactoring by creating a variable to hold the dictionary such as
and then conditionally adding the goal info
and then |
||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,2 +1,188 @@ | ||||||||||||||||||||||||||||||||
from flask import Blueprint | ||||||||||||||||||||||||||||||||
from app import db | ||||||||||||||||||||||||||||||||
from app.models.task import Task | ||||||||||||||||||||||||||||||||
from flask import Blueprint, request, make_response, jsonify | ||||||||||||||||||||||||||||||||
from datetime import datetime | ||||||||||||||||||||||||||||||||
import requests | ||||||||||||||||||||||||||||||||
import flask_migrate | ||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||
from app.models.goal import Goal | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
task_bp = Blueprint("task", __name__, url_prefix='/tasks') | ||||||||||||||||||||||||||||||||
goal_bp = Blueprint("goal", __name__, url_prefix='/goals') | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route("", methods=["POST"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def post_task(): | ||||||||||||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if "title" in request_body and "description" in request_body and "completed_at" in request_body: | ||||||||||||||||||||||||||||||||
new_task = Task(title=request_body["title"],description=request_body["description"], | ||||||||||||||||||||||||||||||||
completed_at=request_body["completed_at"]) | ||||||||||||||||||||||||||||||||
db.session.add(new_task) | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({"task": new_task.to_json()}), 201 | ||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||
return make_response({"details": "Invalid data"}), 400 | ||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider refactoring to handle the 400 response first. This pattern can increase readability.
Suggested change
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route("", methods=["GET"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def get_all_tasks(): | ||||||||||||||||||||||||||||||||
sort_method = request.args.get("sort") | ||||||||||||||||||||||||||||||||
if sort_method == "asc": | ||||||||||||||||||||||||||||||||
tasks = Task.query.order_by(Task.title.asc()) | ||||||||||||||||||||||||||||||||
elif sort_method == "desc": | ||||||||||||||||||||||||||||||||
tasks = Task.query.order_by(Task.title.desc()) | ||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||
tasks = Task.query.all() | ||||||||||||||||||||||||||||||||
task_response_body = [] | ||||||||||||||||||||||||||||||||
for task in tasks: | ||||||||||||||||||||||||||||||||
task_response_body.append(task.to_json()) | ||||||||||||||||||||||||||||||||
return jsonify(task_response_body), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route('/<task_id>', methods=['GET'], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def get_single_task(task_id): # same name as parameter route | ||||||||||||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||||||||||||
if not task: | ||||||||||||||||||||||||||||||||
return "", 404 | ||||||||||||||||||||||||||||||||
return make_response({"task": task.to_json()}), 200 | ||||||||||||||||||||||||||||||||
Comment on lines
+46
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the pattern I was referring to above. First handle the 400 level response, and then get on with the rest of the program. Nice work! |
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route("/<task_id>", methods=['DELETE', 'PUT'], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def delete_or_put_tasks(task_id): | ||||||||||||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||||||||||||
if not task: | ||||||||||||||||||||||||||||||||
return "", 404 | ||||||||||||||||||||||||||||||||
elif request.method == 'DELETE': | ||||||||||||||||||||||||||||||||
db.session.delete(task) | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({ | ||||||||||||||||||||||||||||||||
"details": f'Task {task_id} "{task.title}" successfully deleted' | ||||||||||||||||||||||||||||||||
}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
elif request.method == 'PUT': | ||||||||||||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||||||||||||
task.title = request_body["title"] | ||||||||||||||||||||||||||||||||
task.completed_at = request_body["completed_at"] | ||||||||||||||||||||||||||||||||
task.description = request_body["description"] | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({"task": task.to_json()}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route('/<task_id>/mark_complete', methods=["PATCH"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def mark_complete(task_id): | ||||||||||||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||||||||||||
if task == None: | ||||||||||||||||||||||||||||||||
return make_response(), 404 | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your code has a few different ways of return 400 level errors. To increase readability, try to choose one way and stick with it. For instance, there is this code above |
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if task: | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you've already dealt with |
||||||||||||||||||||||||||||||||
task.completed_at = datetime.utcnow() | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
call_slack(task) | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice use of a helper function! |
||||||||||||||||||||||||||||||||
return make_response({"task": task.to_json()}, 200) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
def call_slack(task): | ||||||||||||||||||||||||||||||||
key = os.environ.get("API_KEY") | ||||||||||||||||||||||||||||||||
url = "https://slack.com/api/chat.postMessage" | ||||||||||||||||||||||||||||||||
slack_str = f"Someone just completed the task {task.title}" | ||||||||||||||||||||||||||||||||
requests.post(url, data={"token":key ,"channel":"general" , "text": slack_str}) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@task_bp.route('/<task_id>/mark_incomplete', methods=["PATCH"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def mark_incomplete(task_id): | ||||||||||||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||||||||||||
if task == None: | ||||||||||||||||||||||||||||||||
return make_response(), 404 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
task.completed_at = None | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({"task": task.to_json()}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route("", methods=["POST"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def post_new_goal(): | ||||||||||||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
if "title" in request_body: | ||||||||||||||||||||||||||||||||
new_goal = Goal(title=request_body["title"]) | ||||||||||||||||||||||||||||||||
db.session.add(new_goal) | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({"goal": new_goal.now_json()}), 201 | ||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||
return make_response({"details": "Invalid data"}), 400 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route("", methods=["GET"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def get_all_goals(): | ||||||||||||||||||||||||||||||||
sort_method = request.args.get("sort") | ||||||||||||||||||||||||||||||||
if sort_method == "asc": | ||||||||||||||||||||||||||||||||
goals = Goal.query.order_by(Goal.title.asc()) | ||||||||||||||||||||||||||||||||
elif sort_method == "desc": | ||||||||||||||||||||||||||||||||
goals = Goal.query.order_by(Goal.title.desc()) | ||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||
goals = Goal.query.all() | ||||||||||||||||||||||||||||||||
goal_response_body = [] | ||||||||||||||||||||||||||||||||
for goal in goals: | ||||||||||||||||||||||||||||||||
goal_response_body.append(goal.now_json()) | ||||||||||||||||||||||||||||||||
return jsonify(goal_response_body), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route('/<goal_id>', methods=['GET'], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def get_single_goal(goal_id): | ||||||||||||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||||||||||||
if not goal: | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||
return "", 404 | ||||||||||||||||||||||||||||||||
return make_response({"goal": goal.now_json()}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route("/<goal_id>", methods=['DELETE', 'PUT'], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def delete_or_put_goals(goal_id): | ||||||||||||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||||||||||||
if not goal: | ||||||||||||||||||||||||||||||||
return "", 404 | ||||||||||||||||||||||||||||||||
elif request.method == 'DELETE': | ||||||||||||||||||||||||||||||||
db.session.delete(goal) | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({ | ||||||||||||||||||||||||||||||||
"details": f'Goal {goal_id} "{goal.title}" successfully deleted' | ||||||||||||||||||||||||||||||||
}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
elif request.method == 'PUT': | ||||||||||||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||||||||||||
goal.title = request_body["title"] | ||||||||||||||||||||||||||||||||
db.session.commit() | ||||||||||||||||||||||||||||||||
return jsonify({"goal": goal.now_json()}), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route("/<int:goal_id>/tasks", methods=["POST"], strict_slashes = False) | ||||||||||||||||||||||||||||||||
def post_new_task(goal_id): | ||||||||||||||||||||||||||||||||
request_body = request.get_json() | ||||||||||||||||||||||||||||||||
task_ids = request_body["task_ids"] | ||||||||||||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||||||||||||
for task_id in task_ids: | ||||||||||||||||||||||||||||||||
task = Task.query.get(task_id) | ||||||||||||||||||||||||||||||||
if task.goal_id != goal_id: | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what this line of code is doing. Let's talk about it in our 1:1. I think these two values will always not be equal because one is an |
||||||||||||||||||||||||||||||||
goal.tasks.append(task) | ||||||||||||||||||||||||||||||||
response_body = { | ||||||||||||||||||||||||||||||||
"id": goal_id, | ||||||||||||||||||||||||||||||||
"task_ids": task_ids | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
return jsonify(response_body), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
@goal_bp.route('/<int:goal_id>/tasks', methods=['GET']) | ||||||||||||||||||||||||||||||||
def get_tasks_goals(goal_id): | ||||||||||||||||||||||||||||||||
goal = Goal.query.get(goal_id) | ||||||||||||||||||||||||||||||||
if not goal: | ||||||||||||||||||||||||||||||||
return '', 404 | ||||||||||||||||||||||||||||||||
return jsonify(goal.full_json()), 200 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Generic single-database configuration. |
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great use of method
to_json
within this method.