Skip to content
fariagallery.com

Virtual Library: my final project, two years on

A library system in Django, built at technical high school in 2024. It teaches more through the mistakes left in the repository than through what worked.

Published
21 hours ago
Updated
20 hours ago
Subject
Python, Django, Security
Work
View the source (opens in a new tab)

Virtual Library was the final project of my technical high school diploma in Internet Computing, delivered in November 2024 at Escola Estadual Prof. Luiz Simione Sobrinho. It was team work, with Caio Cardoso Silva, Gabriel Medeiros, and Heloisa Teodozio.

It is a catalogue system in Django: books, authors, genres, and languages, each physical copy carrying a loan status, user login, and a librarian area that renews due dates. SQLite for the database, HTML templates, a little custom CSS.

The honest part, up front

The project was built on top of the MDN LocalLibrary tutorial, Mozilla’s Django guide. You can see it in the code without effort: the project folder is called locallibrary, the models are Book, BookInstance, Author, Genre, and the author death field is written exactly as in the tutorial, models.DateField('died').

I say that up front because it is the opposite of a weakness. A first contact with a web framework by following a good tutorial is how nearly everyone learns, and hiding it would be the odd choice on a site whose front page says that what did not work gets the same label.

What the team added on top: the Language model, which the tutorial leaves as a closing exercise rather than handing over, the rewritten index, the CSS, and the school’s identity.

What it taught

ORM and migrations. There are five migration files in the repository, and they narrate the model evolving: the first creates the skeleton, the second swaps the example model for the four real ones, the third adds the borrower field, the fourth changes ordering, the fifth introduces language. Reading that sequence is reading the project being thought through.

Real modelling. The central idea of the system is the difference between Book and BookInstance: the book is the work, the instance is the physical copy on the shelf. The library has one Dom Casmurro, but three copies, and only one is on loan. Anyone who has never modelled that assumes a book is a single table, and this distinction is the first modelling lesson worth having.

Permissions, not just login. There is a login screen, password recovery, and an area only a librarian can reach. That is different from “a user is logged in”: it is a user with a role.

What I would do differently today

Here is the real reason for this text. I revisited the repository in August 2026 and found four things I would not let through now.

The Django secret key is in the repository. The SECRET_KEY from settings.py was committed along with everything else, in a public repo. In this specific case the damage is small: it is the development key Django itself generates with the django-insecure- prefix, the project has DEBUG = True and an empty ALLOWED_HOSTS, meaning it never went to production. But the lesson holds in full: keys go in environment variables, not in commits, and git history is permanent.

The database was committed. There is a 245 KB db.sqlite3 in the repository. A development database does not belong in git: it changes constantly, pollutes the history, and depending on what is inside, publishes data about people who never asked to be published.

Compiled files in the repository. All the __pycache__ folders are there. They are artifacts Python generates on its own, and a three line .gitignore would have handled it.

A folder called catalog - Copia. A whole duplicate of the templates was left behind, named the way Windows names things when someone hits Ctrl+C and Ctrl+V. It is the manual backup of someone who does not yet trust version control, and it is exactly what git exists to make unnecessary.

What I did about it

Writing all of that and leaving the repository as it was would have been odd, so I cleaned it up.

The database, the __pycache__ folders, and the duplicate folder came out of the entire history, not just the current state. That distinction is the whole point: removing a file in a new commit does not remove it from the past, and in git the past stays downloadable by anyone. The key now comes from an environment variable. In went a .gitignore, a requirements.txt pinning the Django version used at delivery, and a README explaining how to run the project from scratch, since without a versioned database you have to create one.

Not a line of the 2024 code changed. I compared it file by file, before and after: the 58 files match, and the only difference in the whole repository is the line holding the key.

And there was a surprise waiting. The repository had two commits. Once the database left the history, the second one turned out empty: the only thing it changed was db.sqlite3, which had grown 4 KB because someone opened the system and clicked through a few screens. Months of work fit into a single commit, and the other one was the database getting fatter.

Why this is here

None of those four mistakes shows up in the running site. The system works, the board approved it, the course ended.

They showed up when someone opened the repository, which is exactly what a recruiter does. And I only spotted all four because today I know what to look for, which two years ago I did not.

That is why this project stays in the collection instead of being deleted. The distance between what I built in 2024 and what I can see in 2026 is the most useful information that folder holds.

Back to the blog