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
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions
# More info on Python, GitHub Actions, and Azure App Service: https://aka.ms/python-webapps-actions

name: Build and deploy Python app to Azure Web App - msdcos-poython-postgres-pap3

on:
push:
branches:
- starter-no-infra
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read #This is required for actions/checkout

steps:
- uses: actions/checkout@v4

- name: Set up Python version
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Create and start virtual environment
run: |
python -m venv venv
source venv/bin/activate

- name: Install dependencies
run: pip install -r requirements.txt

# Optional: Add step to run tests here (PyTest, Django test suites, etc.)

- name: Zip artifact for deployment
run: zip release.zip ./* -r

- name: Upload artifact for deployment jobs
uses: actions/upload-artifact@v4
with:
name: python-app
path: |
release.zip
!venv/

deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
permissions:
id-token: write #This is required for requesting the JWT
contents: read #This is required for actions/checkout

steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: python-app

- name: Unzip artifact for deployment
run: unzip release.zip


- name: Login to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID_15D32A133FE345938D0B68C1387A074C }}
tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID_961C12A76F67417695358C3D734F4D13 }}
subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID_55D54E4C2A824EB39284FE19BA8B29CF }}

- name: 'Deploy to Azure Web App'
uses: azure/webapps-deploy@v3
id: deploy-to-webapp
with:
app-name: 'msdcos-poython-postgres-pap3'
slot-name: 'Production'

59 changes: 54 additions & 5 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from datetime import datetime
from datetime import datetime, timezone

from flask import Flask, redirect, render_template, request, send_from_directory, url_for
from flask import Flask, jsonify, redirect, render_template, request, send_from_directory, url_for
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect
Expand Down Expand Up @@ -32,13 +32,19 @@
migrate = Migrate(app, db)

# The import must be done after db initialization due to circular import issue
from models import Restaurant, Review
from models import Restaurant, Review, ImageData

#@app.route('/', methods=['GET'])
#def index():
# print('Request for index page received')
# restaurants = Restaurant.query.all()
# return render_template('index.html', restaurants=restaurants)

@app.route('/', methods=['GET'])
def index():
print('Request for index page received')
restaurants = Restaurant.query.all()
return render_template('index.html', restaurants=restaurants)
images = ImageData.query.all()
return render_template('index.html', images=images)

@app.route('/<int:id>', methods=['GET'])
def details(id):
Expand Down Expand Up @@ -114,6 +120,49 @@ def star_rating(id):

return dict(star_rating=star_rating)

@app.route('/images', methods=['GET'])
def image_table():
print('Request for image table page received')
images = ImageData.query.order_by(ImageData.upload_time.desc()).all()
return render_template('index.html', images=images)

@csrf.exempt
@app.route('/upload_image', methods=['POST'])
def upload_image():
print('Request to upload image received')
if not request.is_json:
return jsonify({"error": "Request must be JSON"}), 400

data = request.get_json()
filename = data.get('filename')
pixel_red = data.get('pixel_red')
pixel_green = data.get('pixel_green')
pixel_blue = data.get('pixel_blue')
username = data.get('username')


if not all([filename, pixel_red, pixel_green, pixel_blue, username]):
return jsonify({"error": "All fields ('filename', 'pixel_red', 'pixel_green', 'pixel_blue', 'username') are required"}), 400

try:
new_image = ImageData(
filename=filename,
pixel_red=pixel_red,
pixel_green=pixel_green,
pixel_blue=pixel_blue,
username=username,
upload_time=datetime.now(timezone.utc)

)
#db.session.create_all()
#db.session.commit()
db.session.add(new_image)
db.session.commit()
return jsonify({"message": "Image uploaded successfully"}), 201
except Exception as e:
db.session.rollback()
return jsonify({"error": str(e)}), 500

@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
Expand Down
12 changes: 6 additions & 6 deletions azureproject/production.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import os

# DATABASE_URI = 'postgresql+psycopg2://{dbuser}:{dbpass}@{dbhost}/{dbname}'.format(
# dbuser=os.getenv('AZURE_POSTGRESQL_USER'),
# dbpass=os.getenv('AZURE_POSTGRESQL_PASSWORD'),
# dbhost=os.getenv('AZURE_POSTGRESQL_HOST'),
# dbname=os.getenv('AZURE_POSTGRESQL_NAME')
# )
DATABASE_URI = 'postgresql+psycopg2://{dbuser}:{dbpass}@{dbhost}/{dbname}'.format(
dbuser=os.getenv('AZURE_POSTGRESQL_USER'),
dbpass=os.getenv('AZURE_POSTGRESQL_PASSWORD'),
dbhost=os.getenv('AZURE_POSTGRESQL_HOST'),
dbname=os.getenv('AZURE_POSTGRESQL_NAME')
)
24 changes: 24 additions & 0 deletions migrations/versions/1920d7e9c1dc_recrear_migración_perdida.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Recrear migración perdida

Revision ID: 1920d7e9c1dc
Revises:
Create Date: 2025-05-08 17:10:57.001491

"""
from alembic import op
import sqlalchemy as sa


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


def upgrade():
pass


def downgrade():
pass
24 changes: 24 additions & 0 deletions migrations/versions/1c80845faa01_unify_heads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Unify heads

Revision ID: d0c7b8e4b57c
Revises: 7d50f8ce1dd1, e95f32cb7145
Create Date: 2025-05-08 22:28:42.064772

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'd0c7b8e4b57c'
down_revision = ('7d50f8ce1dd1', 'e95f32cb7145')
branch_labels = None
depends_on = None


def upgrade():
pass


def downgrade():
pass
37 changes: 37 additions & 0 deletions migrations/versions/2b81d0790f10_a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""a

Revision ID: 2b81d0790f10
Revises: f7006424e5cd
Create Date: 2025-05-08 21:56:08.485113

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '2b81d0790f10'
down_revision = 'f7006424e5cd'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('image_data')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('image_data',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('filename', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('pixel_red', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('pixel_green', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('pixel_blue', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('username', sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column('upload_time', postgresql.TIMESTAMP(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint('id', name='image_data_pkey')
)
# ### end Alembic commands ###
50 changes: 50 additions & 0 deletions migrations/versions/7d50f8ce1dd1_regenerar_migraciones.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Regenerar migraciones

Revision ID: 7d50f8ce1dd1
Revises: 1920d7e9c1dc
Create Date: 2025-05-08 17:11:06.789172

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '7d50f8ce1dd1'
down_revision = '1920d7e9c1dc'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('image_data', schema=None) as batch_op:
batch_op.add_column(sa.Column('pixel_red', sa.String(), nullable=False))
batch_op.add_column(sa.Column('pixel_green', sa.String(), nullable=False))
batch_op.add_column(sa.Column('pixel_blue', sa.String(), nullable=False))
batch_op.add_column(sa.Column('upload_time', sa.DateTime(), nullable=False))
batch_op.alter_column('username',
existing_type=sa.VARCHAR(length=50),
type_=sa.String(length=100),
existing_nullable=False)
batch_op.drop_column('pixel_data')
batch_op.drop_column('upload_datetime')

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('image_data', schema=None) as batch_op:
batch_op.add_column(sa.Column('upload_datetime', postgresql.TIMESTAMP(), autoincrement=False, nullable=True))
batch_op.add_column(sa.Column('pixel_data', sa.TEXT(), autoincrement=False, nullable=False))
batch_op.alter_column('username',
existing_type=sa.String(length=100),
type_=sa.VARCHAR(length=50),
existing_nullable=False)
batch_op.drop_column('upload_time')
batch_op.drop_column('pixel_blue')
batch_op.drop_column('pixel_green')
batch_op.drop_column('pixel_red')

# ### end Alembic commands ###
45 changes: 0 additions & 45 deletions migrations/versions/d0c7b8e4b57c_initial_migration.py

This file was deleted.

Loading