Image Credit:
August 6, 2022 Internship No Comments

I am Dev Anuj Patel, Std. 12th student (2022-23), who got this golden opportunity of an internship project with After a good amount of brainstorming, under the guidance of Mr. Sohil Bhavsar, we decided to develop the web version of VacciSafe, an android application that I had developed earlier, and which still has further scope of improvement.

VacciSafe is a website which helps in planning and keeping track of Vaccine schedules with timely reminders. As we all know, right from birth to around 16 years of age, one is supposed to take 43 vaccines if male or 45 if female. Some are to be taken just after birth, some after 3 months, some after 6 months, and some after 1 year and 6 months and so on. VacciSafe especially helps parents in maintaining and tracking such vaccine schedules for their kids. Each User (e.g. parent) can create multiple “Vaccine Recipients” (e.g. child). During the creation of a new Vaccine Recipient, VacciSafe gathers Gender and Date of Birth, then calculates the Due Date of each particular Vaccine by adding the required number of days, months and years to the recipient’s Date of Birth. At the time of adding a new Vaccine Recipient, VacciSafe marks all those Vaccines which are past their due dates as “Taken”, assuming that the recipient would have already taken those vaccines in the past around their normal due dates. If any recipient has missed a past vaccine, the User can toggle the status of a vaccine between “Taken” and “’Not Taken” to match their particular vaccination history. VacciSafe does not allow future due dates to be marked as “Taken”, meaning you can’t mark a vaccine due next year as “Taken”. VacciSafe sends reminder emails as the due date of a vaccine approaches or is already past the due date and yet not taken.

You can watch the demonstration video here:

VacciSafe – By Dev Anuj Patel

You can review the code on GitHub:

Technical Overview

I had previously used databases like SQLite, MySQL, and Google Cloud SQL but with Sohil Sir, I got this nice opportunity to explore Oracle using the Oracle XE (Express Edition). I used Oracle Database 21c Express Edition (Windows x64) for this project. And I used Django with Python, Bootstrap and JavaScript.

Django Database Models:

  • Vaccines

This table contains all the one-time master data about Vaccines. All the data has been taken from the Government of India’s Health Ministry website (

The columns are a follows:

  • vaccine_name
  • given_at_age_from_year
  • given_at_age_from_month
  • given_at_age_from_weeks
  • details
  • gender

Even if in the future a new vaccine is launched (e.g. we already have new vaccines for Covid) then one can simply add that particular vaccine along with its age & gender eligibility in this table and all new recipients created from then on will have that particular vaccine in the schedule. For existing vaccine recipients, the Vaccine_Records table can be easily manipulated to reflect the appropriate changes if so required.

  • Users

I have implemented Google Sign-In as the mechanism for user authentication. I used Django’s Social Authentication to make things easier since it automatically handles the data entry in the Users table. I primarily use this table to get the email address and full name of the signed in user. Also I have already created an Android Version of VacciSafe which currently doesn’t implement Google Sign-In or any sort of authentication since the main idea was to make it work without the internet as well. So if in future I plan to use Google Authentication then both, the Website and the Android App can operate from a common database with changes being reflected in both.

  • Recipients

Each user can create as many Vaccine Recipients as they want. This table stores information about each Recipient. Columns are as follows:

  • user_fk (foreign key)
  • fname
  • lname
  • date_of_birth
  • gender

According to the Date of Birth provided VacciSafe generates the due date of each vaccine. More on this has been discussed in the recipient creation process. Gender is also a required field since girls are supposed to take two additional vaccines.

  • Vaccine_Records

This table stores all the data about the vaccine schedule of recipients. It gets populated each time when a new recipient is created. This table contains the following columns:

  • recipient_fk (foreign key)
  • vaccine_fk (foreign key)
  • reminder_date (to store the due date)
  • vac_taken_date (stores the date representing status as “Taken”; remains null if not yet taken)

Recipient Creation Process

Each user can have multiple recipients. When a user is logged in then they get the option for creating a new recipient. The form asks for the recipient’s first name and last name along with date of birth and gender. If the gender is ‘Female’ then all the vaccines from the Vaccines table are selected. If not, then all vaccines with ‘ALL’ as gender are selected (thereby leaving the two vaccines for girls). The three ‘given_at_age_from’ column values (no of years, months, and weeks) of the vaccine are added to the Date of Birth of the recipient. If the due date so calculated is before today, then it is assumed that the vaccine is already taken and reminder date as well as vac_taken_date is set to today’s date. If the calculated due date is in the future then the reminder date is set to the due date and vac_taken_date is set as null.

Code and Web GUI –, routes and front-end

index >>

If the user is already logged in then the recipients_page is rendered. Else the Google Login page is rendered. I have overridden Django’s Social Auth Templates (as is evident from the templates folder) to make my GUI cleaner and presentable.

new_recipient and add_recipient >>

The new_recipient route simply renders the form for the creation of a new recipient. The form’s onsubmit has been altered using javascript to ensure validation and make sure that all fields are properly filled. Also no duplicate recipient names can be used under the same ‘top-level-user’. Javascript is then used to add the new recipient by calling POST on add_recipient route. On success, the vaccines_page is rendered which displays the newly created Vaccine Records in a tabular form.

vaccines_page and get_vaccines >>

The vaccines_page route renders the HTML. But the Dnango’s template aren’t enough to dynamically create and set onclick listeners on the Vaccine Name (to show details when clicked on the table cell) and on the status buttons (set ‘Taken’ or ‘Not Taken’ for a vaccine)

toggle_vaccine_status >> Called when a Vaccine status is to be changed (i.e. changed to ‘Taken’ or ‘Not Taken’). If vac_taken_date is null then it is set to today’s date. If it is not null then it is set to null so as to indicate that the vaccine is not taken. The GUI also changes accordingly. If the vaccine is already taken (or marked taken) then the background is green and text is Taken. If the vaccine is not taken (as indicated by the vac_taken_date) then the background is orangish red with text on the button as the reminder date.

Reminder Notification System

In a production environment the code for checking due dates could typically be run every 24 hours, for example say every day at 9AM, but for the sake of testing and demonstration, I had scheduled it to run every ten seconds. To run the server without sending reminder emails every 10 seconds, I would just comment out the import statement of the file from the file. When the code runs (at 9AM every day or after every 10 seconds when not commented out), it first selects all the vaccine records with a null vac_taken_date. Then it gathers a list of all the top-level-users from those vaccine records. Now it associates every recipient in the query set to its respective top-level-user. Next every vaccine record is matched to a recipient. This allows us to send separate emails (one for each recipient) to every top-level-user about their upcoming vaccines. This has been made possible using the file which defines the job and it’s time-interval (e.g. 10 seconds). The file has the code which sends the reminder emails using the SMTPlib library.

Other things to know:

I have used Google Authentication and had to get an OAuth client secret from Google Cloud Console’s credentials tab. In the Authorized redirect URIs and Authorized JavaScript origins, I had first entered localhost. But now I could not run and test my website on other devices on my LAN. Google doesn’t allow you to enter a private IP address either. So I made changes to the “host” file located at “C:\Windows\System32\drivers\etc\hosts” and mapped my server’s private IP ( address to ‘’. So every time I hit on devices with the edited “host” file, it targets my server (i.e. For more information about the host file you may refer to

Once again my sincere thanks to Mr. Sohil Bhavsar and the team at

Thank you,

Dev Anuj Patel

Written by Dev Anuj Patel