From df8e932bf9428c80c4426b1b0b9827eeecda0566 Mon Sep 17 00:00:00 2001 From: Jay Campos Date: Fri, 30 May 2025 11:31:09 +0700 Subject: [PATCH 1/3] Add REST API feature for Notes with CRUD operations and unit tests --- app.py | 10 +++ models.py | 20 ++++- routes/notes_api.py | 46 +++++++++++ templates/pages/placeholder.home.html | 108 ++++++++++++++++++++++++- tests/test_notes_api.py | 112 ++++++++++++++++++++++++++ 5 files changed, 292 insertions(+), 4 deletions(-) create mode 100644 routes/notes_api.py create mode 100644 tests/test_notes_api.py diff --git a/app.py b/app.py index 64d2796c..72c00c9e 100644 --- a/app.py +++ b/app.py @@ -8,6 +8,9 @@ from logging import Formatter, FileHandler from forms import * import os +from routes.notes_api import notes_bp + + #----------------------------------------------------------------------------# # App Config. @@ -15,6 +18,8 @@ app = Flask(__name__) app.config.from_object('config') + +app.register_blueprint(notes_bp) #db = SQLAlchemy(app) # Automatically tear down SQLAlchemy. @@ -91,6 +96,11 @@ def not_found_error(error): app.logger.addHandler(file_handler) app.logger.info('errors') +@app.route('/notes') +def notes_page(): + return render_template('pages/notes.html') + + #----------------------------------------------------------------------------# # Launch. #----------------------------------------------------------------------------# diff --git a/models.py b/models.py index e438d665..a6c13718 100644 --- a/models.py +++ b/models.py @@ -1,6 +1,8 @@ -from sqlalchemy import create_engine +from sqlalchemy import create_engine, Column, Integer, String, Text, DateTime from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base +from datetime import datetime + # from sqlalchemy import Column, Integer, String # from app import db @@ -11,6 +13,22 @@ Base = declarative_base() Base.query = db_session.query_property() +class Note(Base): + __tablename__ = 'notes' + + id = Column(Integer, primary_key=True) + title = Column(String(100), nullable=False) + content = Column(Text, nullable=True) + created_at = Column(DateTime, default=datetime.utcnow) + + def to_dict(self): + return { + "id": self.id, + "title": self.title, + "content": self.content, + "created_at": self.created_at.isoformat() + } + # Set your classes here. ''' diff --git a/routes/notes_api.py b/routes/notes_api.py new file mode 100644 index 00000000..f58a1759 --- /dev/null +++ b/routes/notes_api.py @@ -0,0 +1,46 @@ +from flask import Blueprint, request, jsonify +from models import Note, db_session + +notes_bp = Blueprint('notes', __name__, url_prefix='/api/notes') + +@notes_bp.route('', methods=['POST']) +def create_note(): + data = request.get_json() + if not data or not data.get('title'): + return jsonify({'error': 'Title is required'}), 400 + note = Note(title=data['title'], content=data.get('content')) + db_session.add(note) + db_session.commit() + return jsonify(note.to_dict()), 201 + +@notes_bp.route('', methods=['GET']) +def get_notes(): + notes = db_session.query(Note).all() + return jsonify([note.to_dict() for note in notes]), 200 + +@notes_bp.route('/', methods=['GET']) +def get_note(note_id): + note = db_session.query(Note).get(note_id) + if not note: + return jsonify({'error': 'Note not found'}), 404 + return jsonify(note.to_dict()), 200 + +@notes_bp.route('/', methods=['PUT']) +def update_note(note_id): + note = db_session.query(Note).get(note_id) + if not note: + return jsonify({'error': 'Note not found'}), 404 + data = request.get_json() + note.title = data.get('title', note.title) + note.content = data.get('content', note.content) + db_session.commit() + return jsonify(note.to_dict()), 200 + +@notes_bp.route('/', methods=['DELETE']) +def delete_note(note_id): + note = db_session.query(Note).get(note_id) + if not note: + return jsonify({'error': 'Note not found'}), 404 + db_session.delete(note) + db_session.commit() + return jsonify({'message': 'Note deleted'}), 200 diff --git a/templates/pages/placeholder.home.html b/templates/pages/placeholder.home.html index 45355d68..27dc6b5b 100644 --- a/templates/pages/placeholder.home.html +++ b/templates/pages/placeholder.home.html @@ -2,9 +2,111 @@ {% block title %}Home{% endblock %} {% block content %} -