diff --git a/.gitignore b/.gitignore index 8a189356..d81187e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ -.env -env.py -.vscode -*.py[cod] -__pycache__/ -*.sqlite3 -# static/ -# media/ -.venv/ +.env +env.py +.vscode +*.py[cod] +__pycache__/ +*.sqlite3 +# static/ +# media/ +settings.json +.gitpod.yml +.venv/ diff --git a/hackathon/__init__.py b/hackathon/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackathon/admin.py b/hackathon/admin.py new file mode 100644 index 00000000..81224009 --- /dev/null +++ b/hackathon/admin.py @@ -0,0 +1,16 @@ +from django.contrib import admin +from .models import (Hackathon, + HackAwardCategory, + HackTeam, + HackProject, + HackProjectScore, + HackProjectScoreCategory) + + +# Register your models here. +admin.site.register(Hackathon) +admin.site.register(HackAwardCategory) +admin.site.register(HackTeam) +admin.site.register(HackProject) +admin.site.register(HackProjectScore) +admin.site.register(HackProjectScoreCategory) diff --git a/hackathon/apps.py b/hackathon/apps.py new file mode 100644 index 00000000..fb14bd44 --- /dev/null +++ b/hackathon/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class HackathonConfig(AppConfig): + name = 'hackathon' diff --git a/hackathon/migrations/0001_initial.py b/hackathon/migrations/0001_initial.py new file mode 100644 index 00000000..117b5d58 --- /dev/null +++ b/hackathon/migrations/0001_initial.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1.1 on 2020-10-15 19:02 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Hackathon', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('display_name', models.CharField(default='', max_length=254)), + ('description', models.TextField()), + ('start_date', models.DateTimeField()), + ('end_date', models.DateTimeField()), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackathon_created', to=settings.AUTH_USER_MODEL)), + ('judges', models.ManyToManyField(blank=True, related_name='hackathon_judges', to=settings.AUTH_USER_MODEL)), + ('organiser', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hackathon_organiser', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/hackathon/migrations/0002_auto_20201015_1936.py b/hackathon/migrations/0002_auto_20201015_1936.py new file mode 100644 index 00000000..c5e81fef --- /dev/null +++ b/hackathon/migrations/0002_auto_20201015_1936.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1.1 on 2020-10-15 19:36 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hackathon', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='hackathon', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackathon_created_by', to=settings.AUTH_USER_MODEL), + ), + migrations.CreateModel( + name='HackAwardCategory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('display_name', models.CharField(default='', max_length=254)), + ('description', models.TextField()), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackawardcategory_created_by', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/hackathon/migrations/0003_auto_20201015_2020.py b/hackathon/migrations/0003_auto_20201015_2020.py new file mode 100644 index 00000000..49c4537f --- /dev/null +++ b/hackathon/migrations/0003_auto_20201015_2020.py @@ -0,0 +1,47 @@ +# Generated by Django 3.1.1 on 2020-10-15 20:20 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hackathon', '0002_auto_20201015_1936'), + ] + + operations = [ + migrations.AlterModelOptions( + name='hackawardcategory', + options={'verbose_name_plural': 'Hack award categories'}, + ), + migrations.CreateModel( + name='HackTeam', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('display_name', models.CharField(default='', max_length=254)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackteam_created_by', to=settings.AUTH_USER_MODEL)), + ('participants', models.ManyToManyField(related_name='hackteam', to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='HackProject', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('display_name', models.CharField(default='', max_length=255)), + ('description', models.TextField()), + ('github_link', models.CharField(default='', max_length=255)), + ('collab_link', models.CharField(default='', max_length=255)), + ('submission_time', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackproject_created_by', to=settings.AUTH_USER_MODEL)), + ('mentor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hackproject_mentor', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/hackathon/migrations/0004_auto_20201015_2224.py b/hackathon/migrations/0004_auto_20201015_2224.py new file mode 100644 index 00000000..1a3d1081 --- /dev/null +++ b/hackathon/migrations/0004_auto_20201015_2224.py @@ -0,0 +1,65 @@ +# Generated by Django 3.1.1 on 2020-10-15 22:24 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hackathon', '0003_auto_20201015_2020'), + ] + + operations = [ + migrations.AddField( + model_name='hackawardcategory', + name='hackathon', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='awards', to='hackathon.hackathon'), + preserve_default=False, + ), + migrations.AddField( + model_name='hackawardcategory', + name='winning_project', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='hackathon.hackproject'), + ), + migrations.AddField( + model_name='hackteam', + name='hackathon', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='teams', to='hackathon.hackathon'), + preserve_default=False, + ), + migrations.AddField( + model_name='hackteam', + name='project', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='hackathon.hackproject'), + ), + migrations.CreateModel( + name='HackProjectScoreCategory', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('category', models.CharField(default='', max_length=255)), + ('score', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojectscorecategory_created_by', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name_plural': 'Hack project score categories', + }, + ), + migrations.CreateModel( + name='HackProjectScore', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now)), + ('updated', models.DateTimeField(auto_now=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojectscore_created_by', to=settings.AUTH_USER_MODEL)), + ('judge', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scores', to='hackathon.hackproject')), + ('score', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hackathon.hackprojectscorecategory')), + ], + ), + ] diff --git a/hackathon/migrations/0005_auto_20201016_1951.py b/hackathon/migrations/0005_auto_20201016_1951.py new file mode 100644 index 00000000..00a23f97 --- /dev/null +++ b/hackathon/migrations/0005_auto_20201016_1951.py @@ -0,0 +1,76 @@ +# Generated by Django 3.1.1 on 2020-10-16 19:51 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hackathon', '0004_auto_20201015_2224'), + ] + + operations = [ + migrations.RemoveField( + model_name='hackprojectscorecategory', + name='score', + ), + migrations.AddField( + model_name='hackprojectscore', + name='hackprojectscorecategory', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='hackathon.hackprojectscorecategory'), + preserve_default=False, + ), + migrations.AlterField( + model_name='hackathon', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='hackawardcategory', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='hackawardcategory', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackawardcategories', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hackproject', + name='collab_link', + field=models.URLField(default='', max_length=255), + ), + migrations.AlterField( + model_name='hackproject', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='hackproject', + name='github_link', + field=models.URLField(default='', max_length=255), + ), + migrations.AlterField( + model_name='hackprojectscore', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='hackprojectscore', + name='score', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='hackprojectscorecategory', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='hackteam', + name='created', + field=models.DateTimeField(auto_now_add=True), + ), + ] diff --git a/hackathon/migrations/0006_auto_20201016_2050.py b/hackathon/migrations/0006_auto_20201016_2050.py new file mode 100644 index 00000000..ccd0d5ac --- /dev/null +++ b/hackathon/migrations/0006_auto_20201016_2050.py @@ -0,0 +1,18 @@ +# Generated by Django 3.1.1 on 2020-10-16 20:50 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('hackathon', '0005_auto_20201016_1951'), + ] + + operations = [ + migrations.RenameField( + model_name='hackprojectscore', + old_name='hackprojectscorecategory', + new_name='hack_project_score_category', + ), + ] diff --git a/hackathon/migrations/0007_auto_20201017_1148.py b/hackathon/migrations/0007_auto_20201017_1148.py new file mode 100644 index 00000000..0144e456 --- /dev/null +++ b/hackathon/migrations/0007_auto_20201017_1148.py @@ -0,0 +1,41 @@ +# Generated by Django 3.1.1 on 2020-10-17 11:48 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('hackathon', '0006_auto_20201016_2050'), + ] + + operations = [ + migrations.AlterField( + model_name='hackathon', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackathons', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hackproject', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojects', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hackprojectscore', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojectscores', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hackprojectscorecategory', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackprojectscorecategories', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hackteam', + name='created_by', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackteams', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/hackathon/migrations/__init__.py b/hackathon/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackathon/models.py b/hackathon/models.py new file mode 100644 index 00000000..cc1f1b11 --- /dev/null +++ b/hackathon/models.py @@ -0,0 +1,174 @@ +from django.db import models +from django.contrib.auth.models import User + +# Optional fields are ony set to deal with object deletion issues. +# If this isn't a problem, they can all be changed to required fields. + +# The "updated" field isn't editable in admin. Neither is "submission" field. +# A custom method to auto-fill created_by fields can be made + +# When it seemed relevant, I moved the ForeignKey field to another model and +# used the one listed in the schema as the related_name. I may have been +# erroneous to do so but it can be corrected easily. +# My reasoning is explained in comments above the ForeignKey fields. + + +class Hackathon(models.Model): + """Model representing a Hackathon. It is connected by a foreign key to + User, HackAwards and HackTeam. Optional Fields: judges, organiser. + "awards" and "teams" are related tables. They have been moved to + HackAwardCategory and HackTeam respectively. Please see comments there.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user: One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackathons") + display_name = models.CharField(default="", max_length=254) + description = models.TextField() + start_date = models.DateTimeField() + end_date = models.DateTimeField() + # Hackathons can have numerous judges and + # users could be the judges of more than one Hackathon: Many to Many + judges = models.ManyToManyField(User, + blank=True, + related_name='hackathon_judges') + # One organiser could organise more than one Hackathon: One To Many + organiser = models.ForeignKey(User, + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="hackathon_organiser") + + def __str__(self): + return self.display_name + + +class HackAwardCategory(models.Model): + """Model representing a HackAwardCategory. It is connected by a foreign key to + User, Hackathon and HackProject. Optional fields: winning_project.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user: One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackawardcategories") + display_name = models.CharField(default="", max_length=254) + description = models.TextField() + # a Category will only apply to one Hackathon and + # a Hackathon has numerous categories: One to Many. + # If the category was going to be reused, instead, use Many to Many. + hackathon = models.ForeignKey(Hackathon, + on_delete=models.CASCADE, + related_name="awards") + # One category can have one winner: One to One + winning_project = models.OneToOneField("HackProject", + null=True, + blank=True, + on_delete=models.SET_NULL) + + def __str__(self): + return self.display_name + + class Meta: + verbose_name_plural = "Hack award categories" + + +class HackTeam(models.Model): + """Model representing a HackTeam. It is connected by a foreign key to + User, Hackathon and HackProject. Optional fields: project.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user: One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackteams") + display_name = models.CharField(default="", max_length=254) + # users could be the participants of more than one Hackathon, on different + # teams and a team is made of a number of participants - Many to Many + # Issue is that a user could join more than one team on the same Hackathon. + # Could use a custom save method to prevent it. + participants = models.ManyToManyField(User, + related_name='hackteam') + # A team participates in one Hackathon and + # a Hackathon has numerous teams: One to Many. + hackathon = models.ForeignKey(Hackathon, + on_delete=models.CASCADE, + related_name="teams") + # One to team will have one project: One to One + project = models.OneToOneField("HackProject", + null=True, + blank=True, + on_delete=models.SET_NULL) + + def __str__(self): + return self.display_name + + +class HackProject(models.Model): + """Model representing a HackProject. It is connected by a foreign key to + User and HackProjectScore. Optional Fields: mentor. + Used URLFields for the *_link fields, a CharField with URL validation. + "scores" has been moved to HackProjectScore. See comments there.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user: One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackprojects") + display_name = models.CharField(default="", max_length=255) + description = models.TextField() + github_link = models.URLField(default="", max_length=255) + collab_link = models.URLField(default="", max_length=255) + submission_time = models.DateTimeField(auto_now_add=True) + # A project has one mentor, a mentor has numerous projects: One to Many. + mentor = models.ForeignKey(User, + null=True, + blank=True, + on_delete=models.SET_NULL, + related_name="hackproject_mentor") + + def __str__(self): + return self.display_name + + +class HackProjectScore(models.Model): + """Model representing a HackProjectScore. It is connected by a foreign key to + User, HackProject and HackProjectScoreCategory.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user: One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackprojectscores") + # One Judge can give one score - One to One + judge = models.OneToOneField(User, on_delete=models.CASCADE) + # One score is for one project, a project has numerous scores: One to Many + project = models.ForeignKey(HackProject, + on_delete=models.CASCADE, + related_name="scores") + score = models.IntegerField(default=0) + # A score applies to one category, a category has many scores: One to Many + hack_project_score_category = models.ForeignKey("HackProjectScoreCategory", + on_delete=models.CASCADE) + + def __str__(self): + return f'{self.project}, {self.judge}' + + +class HackProjectScoreCategory(models.Model): + """Model representing a HackProjectScoreCategory. It is connected by a + foreign key to User and HackProjectScore.""" + created = models.DateTimeField(auto_now_add=True) + updated = models.DateTimeField(auto_now=True) + # Each model can only be created by one user - One To Many + created_by = models.ForeignKey(User, + on_delete=models.CASCADE, + related_name="hackprojectscorecategories") + category = models.CharField(default="", max_length=255) + + def __str__(self): + return self.category + + class Meta: + verbose_name_plural = "Hack project score categories" diff --git a/hackathon/tests/__init__.py b/hackathon/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/hackathon/tests/test_models.py b/hackathon/tests/test_models.py new file mode 100644 index 00000000..0c2c3b23 --- /dev/null +++ b/hackathon/tests/test_models.py @@ -0,0 +1,88 @@ +from django.test import TestCase +from django.utils import timezone +from django.contrib.auth.models import User + +from hackathon.models import (Hackathon, + HackTeam, + HackAwardCategory, + HackProject, + HackProjectScore, + HackProjectScoreCategory) + + +class HackathonTests(TestCase): + """Tests fo Hackathon models.""" + + def setUp(self): + """Sets up the models for testing""" + user = User.objects.create(username="testuser") + user.save() + hackathon = Hackathon.objects.create( + created_by=user, + display_name="hacktest", + description="lorem ipsum", + start_date=f'{timezone.now()}', + end_date=f'{timezone.now()}') + hackathon.save() + + team = HackTeam.objects.create( + created_by=user, + display_name="testteam", + hackathon=hackathon) + team.save() + team.participants.set([user]) + + award_category = HackAwardCategory.objects.create( + created_by=user, + display_name="testaward", + description="lorem ipsum", + hackathon=hackathon) + award_category.save() + + project = HackProject.objects.create( + created_by=user, + display_name="testproject", + description="lorem ipsum", + github_link="https://www.test.com/", + collab_link="https://www.test.com/") + project.save() + + score_category = HackProjectScoreCategory.objects.create( + created_by=user, + category="testcategory") + score_category.save() + + score = HackProjectScore.objects.create( + created_by=user, + judge=user, + project=project, + score=1, + hack_project_score_category=score_category) + score.save() + + def test_hackathon_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(Hackathon.objects.get(pk=1)), ('hacktest')) + + def test_hackteam_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(HackTeam.objects.get(pk=1)), ('testteam')) + + def test_hackawardcategory_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(HackAwardCategory.objects.get(pk=1)), + ('testaward')) + + def test_hackproject_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(HackProject.objects.get(pk=1)), ('testproject')) + + def test_hackprojectscore_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(HackProjectScore.objects.get(pk=1)), + ("testproject, testuser")) + + def test_hackprojectscorecategory_str(self): + """Tests the string method on the hackathon.""" + self.assertEqual(str(HackProjectScoreCategory.objects.get(pk=1)), + ('testcategory')) diff --git a/hackathon/urls.py b/hackathon/urls.py new file mode 100644 index 00000000..96f8167f --- /dev/null +++ b/hackathon/urls.py @@ -0,0 +1,5 @@ +from django.urls import path + +urlpatterns = [ + +] diff --git a/hackathon/views.py b/hackathon/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/hackathon/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/main/settings.py b/main/settings.py index 4646cb82..c2024e4a 100644 --- a/main/settings.py +++ b/main/settings.py @@ -29,6 +29,8 @@ "home", "profiles", "crispy_forms", + # M05 App "Hackathon" added + "hackathon", ] MIDDLEWARE = [ diff --git a/main/urls.py b/main/urls.py index 9786d549..22af622a 100644 --- a/main/urls.py +++ b/main/urls.py @@ -6,4 +6,6 @@ path("admin/", admin.site.urls), path("accounts", include("allauth.urls")), path("profile/", include("profiles.urls")), + path("hackathon/", include(("hackathon.urls", "hackathon"), + namespace='hackathon')), ]