diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..633cd56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +[label .gitignore] +db.sqlite3 +*.pyc +.venv/* +.env \ No newline at end of file diff --git a/README.md b/README.md index 398b95d..7947d0a 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,26 @@ [Iridium Tutoring](https://www.iridiumtutoring.org) is a nationwide 501(c)(3) nonprofit tutoring organization serving K-12 students with free, personalized educational support in all subjects. Our mission is to provide high-quality, accessible, and equitable tutoring to students in need, regardless of their background or financial status. We are committed to helping students reach their full potential and achieve academic success. -This dashboard streamlines the tutoring session registration process and tutor sign-up process to a non-Google-Sheets/Forms-hosted platform. Developed by the 2024 Iridium Tutoring director team (Charles Tang). Utilizes Model-View-Template (MVT) architecture for `Tutors`, `Students`, and `Tutoring-Sessions`. - +This dashboard streamlines the tutoring session registration process and tutor sign-up process to a non-Google-Sheets/Forms-hosted platform. Developed by the 2024 Iridium Tutoring's founder, Charles Tang. Utilizes Model-View-Template (MVT) architecture for models Tutors`, `Students`, and `Tutoring-Sessions`; views `studentView`, `tutorView`, `index`, `etc`; and Bootstrapped templates for each view. ## Tech Stack -- **Frontend**: Django, HTML, CSS, JavaScript -- **Backend**: Django, SQLite +- **Frontend**: HTML, CSS (Bootstrap 5.0), JavaScript +- **Backend**: Django, SQLite, Web Mail (SMTP) - **Deployment**: DigitalOcean ## Features -[x] Admin dashboard (manage tutor, student, session registrations) -[x] Student session registration (sign up for tutoring sessions, email confirmation, automatic account generation) -[x] Student dashboard (login/logout, see past/upcoming sessions, register session, see session details, see tutor details) -[x] Tutor session dashboard (login/logout, see available sessions, see historical sessions, sign up for sessions, past taken sessions, add session) -[] Tutor profile dashboard (volunteering hours) -[] Admin dashboard (sort by model, create new tutor form, create new session form) -[] Deployed onto DigitalOcean (thanks to nonprofit credits), subdomain of iridiumtutoring.org +Italicized features are in the implementation stages. +- [x] (MVP #1) Admin dashboard (manage tutor, student, and session registrations) +- [x] (MVP #2) Student session registration (sign up for tutoring sessions, email confirmation, automatic account generation) +- [x] (MVP #3) Student dashboard (login/logout, see past/upcoming sessions, register session, see session details, see tutor details) +- [x] (MVP #4) Tutor session dashboard (login/logout, see available sessions, *see historical sessions*, sign up for sessions, past taken sessions, *add session*) +- [ ] Tutor profile dashboard (volunteering hours) +- [ ] Admin dashboard (sort by model, create new tutor form, create new session form) +- [ ] Deployed onto DigitalOcean (thanks to nonprofit credits), configured DNS for a subdomain (portal.iridiumtutoring.org) ## Notes -Since we are deploying with a SQLite single-file database, we will need to download the database from the server every time we deploy. This is not ideal, but it is the best we can do with our current resources. +Since we are deploying with a SQLite single-file database, we will need to download the database from the server every time we deploy. This is not ideal, but it is the best we can do with our current resources. We will eventually migrate to either PostgreSQL or MySQL, depending on what is more readily available and can fit our needs. ## How To Run We assume you have the latest version of Python installed. @@ -36,7 +36,13 @@ We assume you have the latest version of Python installed. pip install django ``` -3. Run the server. +3. Make migrations +```bash + python manage.py makemigrations + python manage.py migrate +``` + +4. Run the server. ```bash python manage.py runserver ``` diff --git a/db.sqlite3 b/db.sqlite3 index 688cb8c..5dcc15b 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/iridisite/settings.py b/iridisite/settings.py index 62cc3d5..da5b01b 100644 --- a/iridisite/settings.py +++ b/iridisite/settings.py @@ -1,36 +1,26 @@ """ Django settings for iridisite project. - -Generated by 'django-admin startproject' using Django 5.0.2. - -For more information on this file, see -https://docs.djangoproject.com/en/5.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/5.0/ref/settings/ """ from pathlib import Path +from django.core.management.utils import get_random_secret_key +import os +import sys +import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ - # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-4mv49k@ao+x=c37soeh@+r5&^v0*ue_e&kzc(&!gt&g@+u$n++' - # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = [] +SECRET_KEY = SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", get_random_secret_key()) +ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "127.0.0.1,localhost").split(",") +DEBUG = os.getenv("DEBUG", "False") == "True" -EMAIL_HOST = "mail.iridiumtutoring.org" -EMAIL_HOST_USER = "noreply@iridiumtutoring.org" -EMAIL_HOST_PASSWORD = "123456" -EMAIL_PORT = 587 +EMAIL_HOST = os.getenv("EMAIL_HOST") +EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER") +EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD") +EMAIL_PORT = os.getenv("EMAIL_PORT") # Application definition @@ -77,14 +67,21 @@ # Database -# https://docs.djangoproject.com/en/5.0/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', +DEVELOPMENT_MODE = os.getenv("DEVELOPMENT_MODE", "False") == "True" + +if DEVELOPMENT_MODE is True: + DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3"), + } + } +elif len(sys.argv) > 0 and sys.argv[1] != 'collectstatic': + if os.getenv("DATABASE_URL", None) is None: + raise Exception("DATABASE_URL environment variable not defined") + DATABASES = { + "default": dj_database_url.parse(os.environ.get("DATABASE_URL")), } -} # Password validation @@ -128,9 +125,9 @@ # Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/5.0/howto/static-files/ STATIC_URL = 'static/' +STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") # Default primary key field type # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field diff --git a/requirements.txt b/requirements.txt index 242ac79..510ae44 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,41 +1,9 @@ -absl-py==2.1.0 asgiref==3.7.2 -astunparse==1.6.3 -certifi==2024.2.2 -charset-normalizer==3.3.2 -Django==5.0.2 -dm-tree==0.1.8 -flatbuffers==23.5.26 -gast==0.5.4 -google-pasta==0.2.0 -grpcio==1.62.0 -h5py==3.10.0 -idna==3.6 -joblib==1.3.2 -libclang==16.0.6 -Markdown==3.5.2 -markdown-it-py==3.0.0 -MarkupSafe==2.1.5 -mdurl==0.1.2 -ml-dtypes==0.3.2 -namex==0.0.7 -numpy==1.26.4 -opt-einsum==3.3.0 +dj-database-url==2.1.0 +Django==5.0.3 +gunicorn==21.2.0 packaging==23.2 -protobuf==4.25.3 -Pygments==2.17.2 -requests==2.31.0 -rich==13.7.1 -scipy==1.12.0 -setuptools==69.1.1 -six==1.16.0 +psycopg2-binary==2.9.9 sqlparse==0.4.4 -termcolor==2.4.0 -threadpoolctl==3.3.0 typing_extensions==4.10.0 tzdata==2024.1 -urllib3==2.2.1 -Werkzeug==3.0.1 -wheel==0.42.0 -wrapt==1.16.0 -pre-commit diff --git a/tutoring_student/__pycache__/views.cpython-312.pyc b/tutoring_student/__pycache__/views.cpython-312.pyc index efd58ca..dd70656 100644 Binary files a/tutoring_student/__pycache__/views.cpython-312.pyc and b/tutoring_student/__pycache__/views.cpython-312.pyc differ diff --git a/tutoring_student/models.py b/tutoring_student/models.py index 4bdf205..2b043e6 100644 --- a/tutoring_student/models.py +++ b/tutoring_student/models.py @@ -17,12 +17,12 @@ def __str__(self): studentName = models.CharField(max_length=100) email = models.EmailField("Email Address") password = models.CharField(max_length=100, default="123456") - phone = models.CharField(max_length=15, null=True) - location = models.CharField(max_length=100, null=True) + phone = models.CharField(max_length=15, null=True, blank=True) + location = models.CharField(max_length=100, null=True, blank=True) # Additional Information - howDidYouHear = models.CharField(max_length=100, null=True) - additionalComments = models.TextField(null=True) + howDidYouHear = models.CharField(max_length=100, null=True, blank=True) + additionalComments = models.TextField(null=True, blank=True) class Tutor(models.Model): """ @@ -36,8 +36,8 @@ def __str__(self): email = models.EmailField("Email Address") password = models.CharField(max_length=100, default="123456") phone = models.CharField(max_length=15, null=True) - onBoardingDate = models.DateField("Date Onboarded", null=True) - description = models.CharField(max_length=100, null=True) + onBoardingDate = models.DateField("Date Onboarded", null=True, blank=True) + description = models.CharField(max_length=100, null=True, blank=True) class TutoringSession(models.Model): """ @@ -56,7 +56,7 @@ def __str__(self): # Personal Information student = models.ForeignKey(Student, on_delete=models.CASCADE) - tutor = models.ForeignKey(Tutor, on_delete=models.CASCADE, null=True) + tutor = models.ForeignKey(Tutor, on_delete=models.CASCADE, null=True, blank=True) # Useful Functions def was_in_the_past(self): diff --git a/tutoring_student/templates/tutoring_student/tutorView.html b/tutoring_student/templates/tutoring_student/tutorView.html index bd83b95..9cedb6f 100644 --- a/tutoring_student/templates/tutoring_student/tutorView.html +++ b/tutoring_student/templates/tutoring_student/tutorView.html @@ -89,11 +89,12 @@
No tutoring sessions available.
{% endif %}