- Obtain a copy of the source code, either by downloading it in ZIP format and unzipping it into a directory or cloning this repository.
- Create a Python virtual environment in the directory containing the source code--e.g.
python -m venv env
. (Python 3.9 was used in development, but any reasonably recent Python should do.) - Activate the virtual environment--e.g.,
source env/bin/activate
in Linux orenv\scripts\activate
in Windows. - Run
pip install -r requirements.txt
to install dependencies. - Set the environment variable
FLASK_APP
toapp.py
--export FLASK_APP=app.py
in Linux,set FLASK_APP=app.py
in Windows. (Optionally also setFLASK_DEBUG
to1
, which will give you more informative error messages. Only use this for testing.) - Run the command
flask run
, and the development server should start. - Visit
http://localhost:5000
to view and work with the application. (Note: 5000 is the default value for the Flask development server port. If you can't connect, check the server's startup message to see if the value is different.)
(Optionally, you can also run pytest tests/tests.py
to run a small suite of tests.)
As the Flask development server warns you, it's for demo/testing purposes only. In production you would use something much more robust to serve your application, like Nginx and Gunicorn.
- Why Flask? It's small, it's lightweight, and it's fast to develop in. Something like Django comes with a lot of overhead.
- Why SQLite? Obviously, you'd use something much more robust like PostgreSQL in actual production. SQLite handling is built into Python, though, so this avoids the overhead of an RDBMS server and driver dependencies for a smallish demo project like this. (The application's structured so the underlying database could be pretty easily swapped out, though.)
- Why raw SQL instead of an ORM like SQLAlchemy? I've used ORMs before and generally found that for smaller projects like this they introduce more overhead/dependency than they're worth. I'm not opposed to ORMs, but it's generally faster for me to write in raw SQL, especially if the queries start getting large and complex.
- Why Jinja2 (the templating engine built into Flask)? This is where I have to confess to being primarily a back-end developer who's been teaching himself front-end skills when he has spare time. In the last year or so I've been trying to learn Vue.js (since it seems to have the least steep learning curve). I'm much more familiar with Flask's templating engine, though, and I had a base template I could borrow from an existing project, so that's what I went with.
- Actual production-level infrastructure--i.e., database and web server. SQLite and the Flask web server are fine for a quick test/demo, but for real-world use you'd want something like PostgreSQL and Nginx/Gunicorn.
- Some type of access control--logins, permissions, and so on--to restrict the system only to people who should be using it. (For instance, I have a current web application that authenticates users against our LDAP server and then checks an internal table for their permissions.)
- Actual logging. This is alluded to in the comments, but in production you'd want your log messages going into a system where they can be catalogued and searched--something like Splunk.
- If we're sticking with the template engine, I'd want to re-examine the inheritance hierarchy. Some of the templates are just similar enough that they could inherit from common ancestors instead of everything inheriting right from the base template.
- Possibly split up the bug and user functionality into separate Flask blueprints and register them in the main application for neatness. What we have right now is perfectly readable, but it's starting to push the edge of unwieldy.
- In the user edit screen, we're currently updating the first and last name fields in the database even if they haven't actually changed, which works, but isn't ideal. I'd most likely watch for an
onchange
event in the fields and act accordingly. - Add functionality to assign a bug to a user at bug creation. Currently you have to create a bug, go back to the main bug screen, and then assign it, which is an extra step.
- Change the "view individual bug/user" requests from GET to POST. Currently the IDs show up in the URL, which isn't terrible--no one should be able to access those URLs without permission--but ideally you don't want IDs like that exposed.
- Add some sort of text-similarity processing to flag up potential duplicate bugs. Right now there's no prevention in place for filing the same (or similar) bug under two different IDs.