Skip to content
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
51 changes: 22 additions & 29 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from flask import Flask, jsonify, request, Response, render_template

from models.pydantic.models import AnimalCreate, AnimalResponse
from typing import Union
from settings import settings
Expand All @@ -11,35 +10,33 @@

db = init_db(app)


@app.route('/')
def home() -> str:
return render_template('home.html')


@app.route('/animals', methods=['GET'])
def index() -> Response:
animals = Animal.query.all()
return jsonify({"animals": [AnimalResponse.model_validate(animal).model_dump(mode='json') for animal in animals]})

return jsonify({
"animals": [AnimalResponse.model_validate(animal).model_dump(mode='json') for animal in animals]
})

@app.route('/animal', methods=['POST'])
def add_animal() -> tuple[Response, int]:
data = AnimalCreate(**request.get_json())
new_animal = Animal(
animal_type=data.animal_type,
name=data.name,
birth_date=data.birth_date
birth_date=data.birth_date,
breed=data.breed if hasattr(data, 'breed') else None,
photo_url=data.photo_url if hasattr(data, 'photo_url') else None,
)
db.session.add(new_animal)
db.session.commit()
return jsonify(
{
"message": "Animal added successfully!",
"animal": AnimalResponse.model_validate(new_animal).model_dump(mode='json')
}
), 201

return jsonify({
"message": "Animal added successfully!",
"animal": AnimalResponse.model_validate(new_animal).model_dump(mode='json')
}), 201

@app.route('/animal/<int:pk>', methods=['PUT'])
def update_animal(pk: int) -> Union[Response, tuple[Response, int]]:
Expand All @@ -51,44 +48,40 @@ def update_animal(pk: int) -> Union[Response, tuple[Response, int]]:
animal.animal_type = data.animal_type
animal.name = data.name
animal.birth_date = data.birth_date
animal.breed = data.breed if hasattr(data, 'breed') else None
animal.photo_url = data.photo_url if hasattr(data, 'photo_url') else None
db.session.commit()
return jsonify(
{
"message": "Animal updated successfully!",
"animal": AnimalResponse.model_validate(animal).model_dump(mode='json'),
},
)

return jsonify({
"message": "Animal updated successfully!",
"animal": AnimalResponse.model_validate(animal).model_dump(mode='json'),
})

@app.route('/animal/<int:pk>', methods=['GET'])
def retrieve_animal(pk: int) -> Union[Response, tuple[Response, int]]:
animal = Animal.query.get(pk)
if not animal:
return jsonify({"message": "Animal not found"}), 404

return jsonify(
{
"animal": AnimalResponse.model_validate(animal).model_dump(mode='json'),
}
)

return jsonify({
"animal": AnimalResponse.model_validate(animal).model_dump(mode='json'),
})

@app.route('/animal/<int:pk>', methods=['DELETE'])
def delete_animal(pk: int) -> Union[Response, tuple[Response, int]]:
animal = Animal.query.get(pk)
if not animal:
return jsonify({"message": "Animal not found"}), 404

db.session.delete(animal)
db.session.commit()
return jsonify({"message": "Animal deleted successfully!"})

@app.route('/health', methods=['GET'])
def health_check() -> tuple[Response, int]:
return jsonify({"status": "ok"}), 200

def initialize_app():
with app.app_context():
db.create_all()


if __name__ == '__main__':
initialize_app()
app.run(debug=True)
34 changes: 34 additions & 0 deletions migrations/versions/cb3b70320c18_add_breed_and_photo_url_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Add breed and photo_url fields

Revision ID: cb3b70320c18
Revises:
Create Date: 2025-06-03 18:41:47.291628

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'cb3b70320c18'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('animal', schema=None) as batch_op:
batch_op.add_column(sa.Column('breed', sa.String(), nullable=True))
batch_op.add_column(sa.Column('photo_url', sa.String(), nullable=True))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('animal', schema=None) as batch_op:
batch_op.drop_column('photo_url')
batch_op.drop_column('breed')

# ### end Alembic commands ###
34 changes: 0 additions & 34 deletions migrations/versions/e08fc0218f8b_.py

This file was deleted.

34 changes: 34 additions & 0 deletions migrations/versions/ee721f495daf_add_breed_column_to_animal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""add breed column to animal

Revision ID: ee721f495daf
Revises: cb3b70320c18
Create Date: 2025-06-03 18:44:54.253482

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'ee721f495daf'
down_revision = 'cb3b70320c18'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('animal', schema=None) as batch_op:
batch_op.add_column(sa.Column('breed', sa.String(), nullable=True))
batch_op.add_column(sa.Column('photo_url', sa.String(), nullable=True))

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('animal', schema=None) as batch_op:
batch_op.drop_column('photo_url')
batch_op.drop_column('breed')

# ### end Alembic commands ###
15 changes: 14 additions & 1 deletion models/pydantic/models.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from datetime import date
from pydantic import BaseModel, ConfigDict
from pydantic import BaseModel, ConfigDict, Field
from typing import Optional


class AnimalCreate(BaseModel):
animal_type: str
name: str
birth_date: date
breed: Optional[str] = None
photo_url: Optional[str] = None


class AnimalResponse(BaseModel):
Expand All @@ -15,3 +18,13 @@ class AnimalResponse(BaseModel):
animal_type: str
name: str
birth_date: date
breed: Optional[str] = None
photo_url: Optional[str] = None

@property
def age(self) -> int:
today = date.today()
age = today.year - self.birth_date.year - (
(today.month, today.day) < (self.birth_date.month, self.birth_date.day)
)
return age
2 changes: 2 additions & 0 deletions models/sqlalchemy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ class Animal(db.Model):
id = db.Column(db.Integer, primary_key=True)
animal_type = db.Column(db.String, nullable=False)
name = db.Column(db.String, nullable=False)
breed = db.Column(db.String, nullable=True)
birth_date = db.Column(db.Date, nullable=False)
photo_url = db.Column(db.String, nullable=True)
Loading