Humanity is a web application designed with Django. More precisely, the Django project is titled Humanity and its main (and only) application is titled Capsule (short for time capsule). The purpose of most all the files in the project can be found in the Django Documentation, as they are automatically created when starting a Django project.
The capsule folder is where the main part of the project lies. As mentioned above, it is the main application of the project and handles all the features detailed in the documentation. The capsule folder itself contains various folders and files, including: migrations, static, templates, and several Python files.
Migrations refer to the interactions with the project's database. Django allows for easy interaction with the database through Python instead of having to explicitly write SQL queries. In models.py is where all the models (i.e. tables in the database) are declared. Then, actions involving storing of new data, updating existing data, deleting data, etc., are all done through the views.py file.
Here you can find the HTML of the many different views of the application. They all inherit from the same "layout.html" file, which contains the relevant link for scripts, stylesheets, and the overall base template of all the views. Bootstrap components are used in all the templates, including, but not limited to, navigation bars, buttons, alerts, cards, and modals. Relevant information about these can be found in the Bootstrap documentation. Moreover, when displaying forms, I have used the Django Crispy Forms feature which renders the form in a better-styled way. The fields of the forms themselves are declared in the forms.py file.
In this folder is where the CSS file of the application is stored, as well as the logo of the site, and the JavaScript files. CSS was not amply used and was simply employed to align some items to the center of the page, change their font color, and/or specify some margins. In "script.js" lies the script that allows the user to toggle a form to either add or update elements like goals, or journal entries.
The other JavaScript file, namely, "library.js" performs the searching of books and displaying the results to the user through the use of the Google Books API. The script first finds the input from the user (by getting the value of the text input) and performs a query on the API through an AJAX call. The query to the API also has a language restriction of English (to only display books only in this language), and my particular API Key, which was obtained through the Google Developers site. The script then displays the results, including the book's title, author(s), and/or cover photo. For each of these fields, I included a "hidden input," i.e. an input not displayed to the user such that when the user clicks on the accompanying "Select" button to each book, a form gets submitted via POST which is meant to add the book to the user's library. I decided to include these as hidden inputs and not as inputs that could be modified by the user so as to preserve the integrity of the data from Google Books. Another field stored as input is the book description, which is not displayed to the user but is stored in the database so as to be displayed when the user visits the "Book notes" section of each book.
This file is the main controller of the web application. In it are defined several functions which take in an HTTP request (and sometimes other parameters) and then do something with that request, e.g. render a template, redirect the user to another function, or change something in the database. Most all the functions in this file (excluding ones that deal with logging in or registering) use the "@login_required" decorator provided by Django. Broadly, almost all of the functions handle both GET and POST requests, the former generally for rendering a template while the latter is for doing something with the model (e.g. adding a project, deleting a book note, etc.). The general structure of the functions is as follows:
There are three functions that handle everything related to the user's account. There is the login function which makes use of Django's built in login method in order to log the user in. The logout function logs the user out. Finally, the register function creates an account for the user.
For the journal, I implemented a journal function which displays the user's entries and also deals with the addition of a new entry. Then I implemented a view_entry function which displays a specific entry and also handles the updating or deleting of said entry.
For the goals I followed a very similar structure to the journal, namely, there is a goals function which takes in a priority (e.g. daily, weekly, monthly) and displays the user's goals that match that priority, the default priority being daily. The goals functions also deals with the addition of new goals. Then, I decided to include a function called change_goal which handles the completion or deletion of a specific goal. I opted for creating a new function instead of, for instance, adding this functionality to the goals function, in order to make the functions more readable and streamlined. In the other scenario, the goals function would have had to be much more complicated and contain many more conditional statements.
Similar to the journal and goals, for the projects I first created a main projects function which displays the user's projects as a table and also adds a new project. Then, the view_project function displays a specific project and all its information, and also handles a new feature which pertains to the project logs, i.e. the user's recordings of the progress they have made in the project. The view_project then performs the addition of new logs. In order to update the project's information or delete it entirely I created a change_project function which does just that. Finally, I implemented a view_log function which displays a specific project log and also deletes the log (is the user so desires).
The main mini_capsule function displays the user's mini capsules if today is on or after the date specified by the user. In order to do this, the function makes use of the datetime python library and then checks if the year, month, and/or day are on or after the date given by the user. If so, then the capsule is displayed. The user can then view it and/or delete it (which is handled by the view_capsule function). If today is before the date associated with the capsule, then the capsule is not displayed.
In this section, I implemented a library function which renders a template displaying all the books that the user has added via the Add Book page (handled by the add_book function and which relies on the JavaScript file "library.js"). They are displayed as Bootstrap cards with the book's title, author(s), and cover photo. The library function also handles the deletion of books from the user's library. When the user clicks on the "View book" button, they are directed to a page that shows the book's information and the user's notes for that book. This is handled by the view_book function. If there is no cover photo or description of the book in the Google Books API, then a text is displayed that says that these features were not found. If a title and/or author are also not included in the API (highly unlikely) then "undefined" will be displayed. Moreover, the view_book function also performs the addition of book notes, which are displayed as hyperlinks. When the user clicks on a note, the view_note function renders a template displaying that particular note. The view_note function also allows for the updating of the information in the note and deletion of the note.
As mentioned above, the forms.py file create the different forms used in the application as Python classes which can then be called in the "views.py." I decided to include forms to add journal entries, book notes, goals, mini time capsules, projects, and project logs. Each one is a distinct class because I wanted to use different properties as well as different help texts (the text that accompanies the input field in HTML) in each case. I also modified the Django preexisting form for user registration called "UserCreationForm" and created a new form that inherits from this one but also contains additional fields like first name, last name, and email.
In "models.py" is where the database tables are declared, also as Python classes which can be called in "views.py" In "apps.py," the application is given the name of "capsule;" in "urls.py" is where all the url paths of the website are established, including paths for each different feature: logging in/out, deleting account, registering, journal, goals, projects, mini capsules, and the library. Some of these url paths take in a parameter (such as a goal id, or a book id) which will then be necessary for the relevant function in "views.py."
In this folder are located crucial files of the project that are the behind the integration of Django. These are files created automatically by Django and which contain important settings and configurations so as to allow the use of the framework and features like Django Crispy Forms. All the relevant information about these files can be found in the Django Documentation. In this case, the changes made were to the "settings.py" file were I included lines to enable the use of Django Crispy Forms as well as to integrate Heroku into the site and declare it as an allowed host.
In order to integrate Heroku, I first had to include it in the "settings.py" file as by calling <django_heroku.settings(locals())> which will set up the application so as to be hosted by Heroku, and which requires the django-heroku library that can be installed through . Additionally, Heroku requires the addition of "Procfile" whose purpose is to indicate Heroku to serve the application using the web server known as Gunicorn. As stated in the CS50 Read the Docs: "That file will tell Heroku to look in a file called application.py for a variable called app and serve it with Gunicorn, a production-quality web server." Heroku also requires the addition of a "requirements.txt" and "runtime.txt" file. The former includes the necessary libraries for the application (in this case, python-dotenv, dj-database-url, Django, django-crispy-forms, django-heroku, gunicorn, heroku, Jinja2, psycopg2, and whitenoise). The Python version used in this site is declared in "runtime.txt". Finally, Heroku also creates an additional folder called "staticfiles" which can be ignored in this case.