You will do Part 3 of Project 1 with the same team as for Parts 1 and 2. If your team partner dropped the class and you did not submit a contingency plan for this with your Part 1 submission, then unfortunately you will still have to complete the whole project by yourself. If your team partner dropped the class and you did submit a contingency plan for this with your Part 1 submission, then you are welcome to switch to this reduced version of your project.
In this final part of Project 1, you will finish building the application that you proposed in Part 1, on top of the database that you created in Part 2. For the final evaluation of Project 1, you will need to submit your code for your application and a README file on Gradescope by Thursday November 19 at 5 p.m. ET (see below for further instructions). Also, both team members will meet with your project mentor on Friday November 20 or Monday November 23. Your project mentor will contact you shortly to schedule a 15-minute meeting for those days. Your implementation will be on Python 3 using Flask, and should satisfy these requirements:
The following resources may be helpful for learning both Python and Flask:
Your job is to implement your proposed web application. To help you
out, we have provided a bare-bones Flask web
application, server.py, available
here. It provides code that connects to a database URL, and a
default index page. Take a look at the comments
in server.py to see how to use or modify the server.
In particular, note that you will need to configure your PostgreSQL
username and password in a private .env file for local
development, and through Secret Manager on Cloud Run, as described
below, rather than include them in server.py.
You
will need to connect to your database from Part 2. Please read all
these directions. Once you get it running, you should start working on
your custom logic.
Important: The starter uses Python 3.14. Please keep
requirements.txt, Procfile, and
.python-version at the root of your repository, so that
Google Cloud can build and run your application.
We use a Python package called SQLAlchemy to simplify
our work for connecting to the database. For
example, the following code loads useful functions from the package:
from sqlalchemy import *
SQLAlchemy is able to connect to many different types
of DBMSs, including SQLite, PostgreSQL, MySQL, and Oracle. Each such
DBMS is called an "engine." The create_engine() function
sets up the configuration for the specific DBMS we want to connect
to:
engine = create_engine(DATABASEURI)
Here, DATABASEURI denotes the database connection URL.
The starter builds this URL from your database settings.
Given an engine, we can then connect to it (this is similar to
how psql connects to our class's PostgreSQL database
server):
conn = engine.connect()
At this point, the conn connection object can be used
to execute queries to the database, which must be "wrapped"
with text() as below. For queries that change data,
follow the query with conn.commit() to save the changes.
This is basically what psql is doing under the
covers:
cursor = conn.execute(text("select 1"))
The execute function takes a SQL query string as input
and returns a cursor object. You can think of this as an
iterator over the result relation. This means you can run SELECT
* on, say, a million-row table and not run out of
memory. Instead of receiving the entire result at once, this object
lets you treat the result as an iterator and call next()
on it, or loop through it. See the
SQLAlchemy
documentation for a detailed description.
# this fetches the first row if called right after # the execute function above. It also moves the # iterator to the next result row. record = cursor.fetchone() # this will fetch the next record, or None if # there are no more results. second_record = cursor.fetchone() # this loops through the results of the cursor one by one for row in cursor: print (list(row))
The above description is a way to directly write and run SQL queries as strings, and directly manipulate the result relations. SQLAlchemy also includes an Object Relational Mapper that provides an interface that hides SQL query strings and result sets from you. In this project, you will directly write and run SQL queries, and cannot use any ORM functionality.
IMPORTANT NOTE: Your code should avoid the SQL injection vulnerability that we discussed in class. Specifically, your code should never build "raw" query strings for the database using user input, but rather you should use parameters, etc. as discussed in class. Your grade for the project will suffer if your code does not avoid SQL injection vulnerabilities.
Since you are working collaboratively with your teammate,
we require you to use the version control
system git for your code
on GitHub. You should use
a private repository on GitHub for this project.
We cover below the basics of git
and GitHub. With this setup, you can code on your own
desktop, commit and push your changes to the GitHub
repository, and then have the updated changes deployed automatically
on Google Cloud Run. You can also code without your teammate being in the
same room, and your teammate will be aware of the changes after
"pulling" the code from GitHub. Conversely, your
teammate will also be able to contribute to the same code repository,
so you can both work collaboratively. Please follow these steps to get
started with git and GitHub:
GitHub. You will need to
provide/verify your email address and provide a username. There is
no requirement on what email or username you use here. Your teammate
should also register for a different account, so that you both have
access to the code repository.GitHub.
Create a repository by clicking
on Create a new
repository.main as the default branch.<REPO_URL>, go to the
webpage <REPO_URL>/settings/access by manually
adding "/settings/access" to the URL (e.g., if your repository is at
https://github.com/abc234/cs4111, then go to
https://github.com/abc234/cs4111/settings/access). Click "Add
people" and then enter your teammate's GitHub username or
email. Then click "Add <EMAIL/USERNAME> to this
repository”. Your teammate will receive an invitation by email,
which your teammate should accept.git repository, and
push the starter files to GitHub. Run the commands one
line at a time and replace all points that are surrounded by "<
>" with your information (for example, "<your full name>"
should be changed to "Luis Gravano" for the instructor).
Use the HTTPS webpage address of your team's repository for
<REPO_URL>, without a trailing .git.
This does not require setting up an SSH key. If you do not already
have HTTPS authentication configured, follow the instructions
available here
to create a personal access token with read and write access to your
repository's contents. When Git asks for your password, use the
token, not your GitHub account password. Do not put the token in the
repository URL or in your source files.
Important: Keep proxy-key.json outside
the starter directory. Store your local PostgreSQL credentials only
in the ignored .env file described below, not in your
source code. Never commit credentials.
# download and extract our skeleton Flask web application cd ~ # Option 1: on MacOS, use the built-in curl command: curl -LO https://www.cs.columbia.edu/~gravano/cs4111/Proj1-3/webserver.tar # Option 2: Alternatively, if Homebrew is available on your computer, install wget: brew install wget # ... and then: wget https://www.cs.columbia.edu/~gravano/cs4111/Proj1-3/webserver.tar tar xf webserver.tar mv webserver <projectname> cd <projectname> # configure your git environment git config --global user.name "<your full name>" git config --global user.email "<email you used to register for GitHub>" # initialize git repository, and push the skeleton files up to the server git init -b main # use the HTTPS repository address from Step 4, not an SSH address git remote add origin <REPO_URL>.git # include hidden starter files, while respecting .gitignore git add . git status git commit -m "initial commit" git push -u origin main # don't enter your GitHub password here; instead, use the personal access token as discussed aboveYou have now created a local
git repository, made your
first commit, and pushed the starter files onto GitHub.
Your usual workflow after these initial steps will be a bit different
than this, as described in the next step.git will typically comprise the
following steps:
GitHub
repository so that your code is up-to-date: git
pull. Note that this step is necessary because, when
working on a project with a teammate, your teammate may have
updated and pushed the code while you were not working on the
project, so you should always pull the changes before beginning to
work on a new revision.git thinks you have changed: git
statusserver.py
and README, then run: git add server.py
READMEgit commit -m "added feature X"GitHub
server: git push. Once you have completed the Cloud
Run setup below, changes pushed to main will deploy
automatically. If you are working on another branch, merge your
changes into main when they are ready to deploy.GitHub, as discussed in the "Running your application..."
section below.) So if you carried out
Step 5 above for your team, then your teammate will need to perform
the following steps to get a copy of the code on their desktop or
laptop. Similarly, you will have to perform the steps below for any
new computer that you want to use to continue developing your code:
# configure your git environment, as in Step 5 git config --global user.name "<your full name>" git config --global user.email "<email you used to register for GitHub>" # clone (i.e., download) the repository onto your local machine # use the username of the owner of the repository here git clone <REPO_URL>.git # you're done setting up; you can now continue as in Step 6
git provides many other powerful functions that we
haven't talked about. For more information, you can refer
to this tutorial,
and documentation on that website. If you encounter a problem with
git, you can typically do a quick search with the error
message and get a lot of helpful information
online. Feel free also to come to office hours with any of your
questions about git and GitHub.
Each teammate should follow these steps on the computer they use for development, after downloading or cloning the starter. The commands below use a macOS or Linux terminal.
server.py), create a virtual environment,
and install the required Python packages:
python3.14 -m venv .venv source .venv/bin/activate python -m pip install -r requirements.txtRun
source .venv/bin/activate again whenever you open a
new terminal to work on the application..env in the same directory as
server.py, with your PostgreSQL credentials from Part 2:
DB_USER='<your PostgreSQL username>' DB_PASSWORD='<your PostgreSQL password>' DB_HOST=127.0.0.1 DB_PORT=5454 DB_NAME=proj1part2Replace the placeholders with your own values, keeping the quotes. These are your PostgreSQL credentials, not your Google or GitHub credentials. Flask loads this file when you run
python server.py.
The starter's .gitignore excludes .env and
.venv/; never commit or submit them. Each teammate
creates their own local file. Cloud Run does not receive this file:
configure its settings separately using the setup directions below.127.0.0.1.) For this, follow the
download instructions for your operating system
to install the Cloud SQL Auth Proxy. Keep the proxy binary and your existing
proxy-key.json from Part 2 (which you received by email from
us for Part 2) outside the project directory;
you do not need a new key. In a separate terminal, from the directory
containing the proxy binary, run:
./cloud-sql-proxy --credentials-file="<full path to proxy-key.json>" --address=127.0.0.1 --port=5454 coms4111-db-ta:us-east1:server-4111-fall-2026Replace the key path with the location on your computer. Leave this terminal and the proxy running while you develop.
python server.pyOpen http://127.0.0.1:8111/ in your browser. If the example table is missing, use the Initialize example table button, then test the Add form. Do not initialize over meaningful existing data. Stop Flask with Control-C and restart it after changing your code or
.env. This development server is only for local testing;
Cloud Run uses the Procfile instead.Once you have developed (a preliminary version of) your web application, you will deploy it to Google Cloud Run, as follows
GitHub repository
to Cloud Run, configure Secret Manager and the Cloud SQL Auth Proxy
sidecar, and allow public access. These instructions use your
existing project, Compute Engine default service account,
proxy-key.json, and PostgreSQL credentials from Part 2.
Enable the additional APIs and grant the required roles as
directed.GitHub repository on
main. (See Step 6 above.)You will need this URL when presenting the project to your mentor. Please do not delete or disable your Cloud Run service when you are ready to submit, so that the URL that you include with your project submission works.
Keeping your application running for your meeting with your
mentor: Cloud Run manages the application process for you.
You do not need to leave a virtual machine running or use
screen. Please check that your application is accessible
without signing in to Google before your meeting.
You will need to submit your code for your application and a README file on Gradescope by Thursday November 19 at 5 p.m. ET. Just as for Parts 1 and 2, you should submit your project exactly once per team, rather than once per student. (Click on "Add Group Member" after one of you has submitted your project.) Here are the rest of the instructions for your electronic submission:
.env, .venv/, proxy-key.json,
or your database passwords.tar -cvf proj1-3.tar proj1-3 and then run gzip proj1-3.tar.In summary, you need to submit on Gradescope exactly two files: (1) your proj1-3.tar.gz file with your code and (2) your uncompressed README file. You need to submit these two files by Thursday November 19 at 5 p.m. ET.
IMPORTANT NOTE: You can use grace late days as usual, but you need to make sure that you schedule your meeting with your project mentor so that you have submitted your files on Gradescope before the meeting. The grace late days will be computed with respect to the time of your submission on Gradescope.
Additionally, both teammates in each team will meet together with their project mentor on Friday November 20 or Monday November 23. Your project mentor will email you shortly to schedule a 15-minute meeting for those days. (If you haven't received an email from your project mentor by Monday November 9, please contact your mentor.) During the meeting with your project mentor, you will show your mentor your application using a regular web browser, by sharing your screen during the online meeting:
Your grade for Part 3 of Project 1 will be a function of how well your application (which should be up and running) matches your specification that you submitted as Part 1, of how well you have incorporated any feedback that your project mentor has given you, and of how well you have followed the guidelines above. Part of your grade will be a function of how well you avoid the SQL injection vulnerability that we discussed in class (see also above). Your grade will not be influenced by how fancy the web-based user interface to your application is. It is sufficient and perfectly fine for this interface to be plain and simple as long as it supports the functionality that you indicated earlier, following the guidelines above about not having to type SQL commands, not "locking up" on unexpected input, etc.