Skip to content
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

c15 Accelerate - Regina Tam, Lilia Paz, Trish Griego #9

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from 7 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
17 changes: 14 additions & 3 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -9,23 +9,34 @@
migrate = Migrate()
load_dotenv()


def create_app():
def create_app(test_config=None):
app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False

app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
if test_config is None:
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")

# Import models here for Alembic setup
# from app.models.ExampleModel import ExampleModel
from app.models.board import Board
from app.models.card import Card

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

# Register Blueprints here
# from .routes import example_bp
from .routes import boards_bp
from .routes import cards_bp

# app.register_blueprint(example_bp)
app.register_blueprint(boards_bp)
app.register_blueprint(cards_bp)

CORS(app)
return app
9 changes: 9 additions & 0 deletions app/models/board.py
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
from sqlalchemy.orm import backref
from app import db

class Board(db.Model):
board_id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String)
owner = db.Column(db.String)
cards = db.relationship("Card", backref="board", lazy=True)
# not sure if we actually need cards here.
# sort of like we had tasks.
8 changes: 8 additions & 0 deletions app/models/card.py
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
from app import db

class Card(db.Model):
card_id = db.Column(db.Integer, primary_key=True)
message = db.Column(db.String)
likes_count = db.Column(db.Integer)
board_id = db.Column(db.Integer, db.ForeignKey("board.board_id"), nullable=False)
# would we ever have a case where it would be ok
# for this to be null ?
64 changes: 63 additions & 1 deletion app/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,66 @@
from flask import Blueprint, request, jsonify, make_response
from app import db
from app.models.board import Board
from app.models.card import Card
from dotenv import load_dotenv
import requests
import os

# example_bp = Blueprint('example_bp', __name__)
load_dotenv()
boards_bp = Blueprint("boards", __name__, url_prefix="/boards")
cards_bp = Blueprint("cards", __name__, url_prefix="/cards")

@boards_bp.route("", methods=["GET", "POST"])
def handle_boards():
if request.method == "GET":
boards = Board.query.all()
boards_response = []

for board in boards:
boards_response.append({
"board_id": board.board_id,
"title": board.title,
"owner": board.owner
})
print('we are in the get request')
return make_response(jsonify(boards_response), 200)
elif request.method == "POST":
request_body = request.get_json()
if "title" not in request_body or "owner" not in request_body:
return {
"details": f"Invalid data"
}, 400
new_board = Board(
title=request_body["title"],
owner=request_body["owner"]
)
db.session.add(new_board)
db.session.commit()

return make_response({
"board": {
"id": new_board.board_id,
"title": new_board.title,
}
}, 201)

# needed to delete boards to test functionality.
# We don't need to keep this production.s
@boards_bp.route("/<board_id>", methods=["DELETE"])
def handle_board(board_id):
board = Board.query.get(board_id)
print('board ---> ', board)

if request.method == "DELETE":
if board is None:
return make_response(f"Board {board_id} not found. ", 404)

db.session.delete(board)
db.session.commit()

return make_response(
{
"details":
f"Board: {board.board_id} with title: {board.title}. Successfully deleted"
}
)
163 changes: 163 additions & 0 deletions crud_plans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Must Ensure the following CRUD paths work:
~~- [ ] GET /boards~~
~~- [ ] POST /boards~~

- [ ] GET /boards/<board_id>/cards
- [ ] POST /boards/<board_id>/cards
- [ ] DELETE /cards/<card_id>
- [ ] PUT /cards/<card_id>/like


### 1. Get Boards: Getting saved Boards
- [ ] GET /boards

As a client, I want to be able to make a `GET` request to `/boards` when there is at least one but possibly many saved boards and get this response:
`200 ok`

```json
[
{
"board_id": 1,
"title": "Literary Quotes",
"owner": "Octavia Butler"
},
{
"board_id": 2,
"title": "Supreme Court Quotes",
"owner": "Ruth Bader Ginsburg"
},
{
"board_id": 3,
"title": "Jokes",
"owner": "Really Funny Person"
}
]
```

### 2. Create a Board: need to decide what could be valid..
- [ ] POST /boards

As a client, I want to be able to make a `POST` request to `/boards` with the following HTTP request body


```json
{
"title": "Brand New Board",
"owner": "Marry Poppins"
}
```

and get this response:

`201 CREATED`

```json
{
"board": {
"board_id": 1,
"title": "Brand New Board",
"owner": "Marry Poppins"
}
}
```
So that I know I succesfully created a Board that is saved in the databse.

******this might need to change its shape. Since it seems possible to have a many to many relationship here****

Question: There could be many boards with many cards...? If so, changes my models a bit. I think.

### Get Boards: No saved Boards

### Get one Board: one saved Board
As a client, I want to be able to make a `GET` request to `/boards/1` when there is at least one saved board and get this response:

`200 ok`
```json
{
"board": {
"board_id": 1,
"title": "New Board for me",
"owner": "Spice Girls"
}
}
```

### Get One Board: No matching Boards
As a client, I want to be able to make a `GET` request to `/boards/1` when there are no matching boards and get this response:

`404 Not Found`

No response body.

### Update Board
As a client, I want to be able to make a `PUT` request to `/boards/1` when there is at least one saved board with this request body:

```json
{
"title": "New name for fancy board",
"owner": "Morty"
}
```

and get this response:
`200 ok`
```json
{
"board": {
"board_id": 1,
"title": "New name for fancy board",
"owner": "Morty"
}
}
```

### Update Board: No matching Board
As a client, I want to be able to make a `PUT` request to `/boards/2` when there are no matching tasks with this request body:

```json
{
"title": "New title for board",
"owner": "Trish"
}
```
and get this response:
`404 Not Found`
No response body

### Delete Board: Deleting a board

### Delete Board: No Matching Board

***
Need to decide on what circumstance will we not allow a database creation to begin.
- example
-- when no title is provided?
-- when no owner is provided?

### Create a Board: Invalid Board With Missing Data **

<hr />

# Need to go through crud for Cards like I did for board above.

### Create a Card: valid card

### Get Cards: Getting saved cards

### Get Cards: No saved Cards

### Get One Card: One saved Card

### Get One Card: No matching Card

### Update Card:

### Update Card: No matching Card

### Delete Card: Deleting a Card

### Delete Card: No matching Card

### Create a Card: Invalid Card with missing data


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