Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/prompts/update-octofit-tracker-app.prompt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mode: 'agent'
model: GPT-4.1

# Django App Updates

- All Django project files are in the `octofit-tracker/backend/octofit_tracker` directory.

1. Update `settings.py` for MongoDB connection and CORS.
2. Update `models.py`, `serializers.py`, `urls.py`, `views.py`, `tests.py`, and `admin.py` to support users, teams, activities, leaderboard, and workouts collections.
3. Ensure `/` points to the api and `api_root` is present in `urls.py`.
9 changes: 5 additions & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
"args": ["runserver", "0.0.0.0:8000"],
"django": true,
"justMyCode": true,
"python": "${workspaceFolder}/octofit-tracker/backend/venv/bin/python",
"python": "/workspaces/skills-build-applications-w-copilot-agent-mode/.venv/bin/python",
"env": {
"PYTHONPATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin/python",
"VIRTUAL_ENV": "${workspaceFolder}/octofit-tracker/backend/venv",
"PATH": "${workspaceFolder}/octofit-tracker/backend/venv/bin:${env:PATH}"
"CODESPACE_NAME": "${env:CODESPACE_NAME}",
"PYTHONPATH": "/workspaces/skills-build-applications-w-copilot-agent-mode/.venv/bin/python",
"VIRTUAL_ENV": "/workspaces/skills-build-applications-w-copilot-agent-mode/.venv",
"PATH": "/workspaces/skills-build-applications-w-copilot-agent-mode/.venv/bin:${env:PATH}"
}
},
{
Expand Down
Binary file added octofit-tracker/backend/db.sqlite3
Binary file not shown.
22 changes: 22 additions & 0 deletions octofit-tracker/backend/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'octofit_tracker.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
Empty file.
8 changes: 8 additions & 0 deletions octofit-tracker/backend/octofit_tracker/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.contrib import admin
from .models import User, Team, Activity, Leaderboard, Workout

admin.site.register(User)
admin.site.register(Team)
admin.site.register(Activity)
admin.site.register(Leaderboard)
admin.site.register(Workout)
16 changes: 16 additions & 0 deletions octofit-tracker/backend/octofit_tracker/asgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
ASGI config for octofit_tracker project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'octofit_tracker.settings')

application = get_asgi_application()
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from django.core.management.base import BaseCommand
from django.conf import settings
from djongo import models
from pymongo import MongoClient

class Command(BaseCommand):
help = 'Populate the octofit_db database with test data'

def handle(self, *args, **options):
client = MongoClient(host='localhost', port=27017)
db = client['octofit_db']

# Drop collections if they exist
db.users.drop()
db.teams.drop()
db.activities.drop()
db.leaderboard.drop()
db.workouts.drop()

# Create unique index on email for users
db.users.create_index([('email', 1)], unique=True)

# Sample users (super heroes)
users = [
{'name': 'Superman', 'email': '[email protected]', 'team': 'DC'},
{'name': 'Batman', 'email': '[email protected]', 'team': 'DC'},
{'name': 'Wonder Woman', 'email': '[email protected]', 'team': 'DC'},
{'name': 'Iron Man', 'email': '[email protected]', 'team': 'Marvel'},
{'name': 'Captain America', 'email': '[email protected]', 'team': 'Marvel'},
{'name': 'Black Widow', 'email': '[email protected]', 'team': 'Marvel'},
]
db.users.insert_many(users)

# Teams
teams = [
{'name': 'Marvel', 'members': ['Iron Man', 'Captain America', 'Black Widow']},
{'name': 'DC', 'members': ['Superman', 'Batman', 'Wonder Woman']},
]
db.teams.insert_many(teams)

# Activities
activities = [
{'user': 'Superman', 'activity': 'Flying', 'duration': 120},
{'user': 'Batman', 'activity': 'Martial Arts', 'duration': 90},
{'user': 'Iron Man', 'activity': 'Weight Lifting', 'duration': 60},
]
db.activities.insert_many(activities)

# Leaderboard
leaderboard = [
{'team': 'Marvel', 'points': 250},
{'team': 'DC', 'points': 200},
]
db.leaderboard.insert_many(leaderboard)

# Workouts
workouts = [
{'name': 'Hero HIIT', 'description': 'High intensity interval training for heroes.'},
{'name': 'Power Yoga', 'description': 'Yoga for strength and flexibility.'},
]
db.workouts.insert_many(workouts)

self.stdout.write(self.style.SUCCESS('octofit_db database populated with test data.'))
33 changes: 33 additions & 0 deletions octofit-tracker/backend/octofit_tracker/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from djongo import models

class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
team = models.CharField(max_length=50)
def __str__(self):
return self.name

class Team(models.Model):
name = models.CharField(max_length=50)
members = models.JSONField()
def __str__(self):
return self.name

class Activity(models.Model):
user = models.CharField(max_length=100)
activity = models.CharField(max_length=100)
duration = models.IntegerField()
def __str__(self):
return f"{self.user}: {self.activity}"

class Leaderboard(models.Model):
team = models.CharField(max_length=50)
points = models.IntegerField()
def __str__(self):
return f"{self.team}: {self.points}"

class Workout(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
def __str__(self):
return self.name
27 changes: 27 additions & 0 deletions octofit-tracker/backend/octofit_tracker/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from rest_framework import serializers
from .models import User, Team, Activity, Leaderboard, Workout

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'

class TeamSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = '__all__'

class ActivitySerializer(serializers.ModelSerializer):
class Meta:
model = Activity
fields = '__all__'

class LeaderboardSerializer(serializers.ModelSerializer):
class Meta:
model = Leaderboard
fields = '__all__'

class WorkoutSerializer(serializers.ModelSerializer):
class Meta:
model = Workout
fields = '__all__'
147 changes: 147 additions & 0 deletions octofit-tracker/backend/octofit_tracker/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
"""
Django settings for octofit_tracker project.

Generated by 'django-admin startproject' using Django 4.1.7.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path

# 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/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-$$q=lu7(%(*qfd2fpuj6a*%fuikg-e4g5_(wc*ny#0%o0vc*3o'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

import os
CODESPACE_NAME = os.environ.get('CODESPACE_NAME')
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
if CODESPACE_NAME:
ALLOWED_HOSTS.append(f"{CODESPACE_NAME}-8000.app.github.dev")


# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'octofit_tracker',
'rest_framework',
'djongo',
'corsheaders',
]

MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'octofit_tracker.urls'

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

WSGI_APPLICATION = 'octofit_tracker.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
'default': {
'ENGINE': 'djongo',
'NAME': 'octofit_db',
'ENFORCE_SCHEMA': False,
'CLIENT': {
'host': 'localhost',
'port': 27017,
'username': '',
'password': '',
'authSource': 'admin',
},
}
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'

# CORS settings
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = ['*']
CORS_ALLOW_METHODS = ['*']

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
28 changes: 28 additions & 0 deletions octofit-tracker/backend/octofit_tracker/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from django.test import TestCase
from .models import User, Team, Activity, Leaderboard, Workout

class UserModelTest(TestCase):
def test_create_user(self):
user = User.objects.create(name='Test', email='[email protected]', team='Marvel')
self.assertEqual(user.name, 'Test')
self.assertEqual(user.team, 'Marvel')

class TeamModelTest(TestCase):
def test_create_team(self):
team = Team.objects.create(name='Marvel', members=['Test'])
self.assertEqual(team.name, 'Marvel')

class ActivityModelTest(TestCase):
def test_create_activity(self):
activity = Activity.objects.create(user='Test', activity='Running', duration=30)
self.assertEqual(activity.activity, 'Running')

class LeaderboardModelTest(TestCase):
def test_create_leaderboard(self):
lb = Leaderboard.objects.create(team='Marvel', points=100)
self.assertEqual(lb.team, 'Marvel')

class WorkoutModelTest(TestCase):
def test_create_workout(self):
workout = Workout.objects.create(name='Test Workout', description='Test Desc')
self.assertEqual(workout.name, 'Test Workout')
Loading