Skip to content

Commit 14ebbdf

Browse files
committed
initial commit
0 parents  commit 14ebbdf

21 files changed

+627
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/venv/
2+
.idea
3+
/media/
4+
/db.sqlite3

api/__init__.py

Whitespace-only changes.

api/admin.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.contrib import admin
2+
3+
from .models import Hackathon, Submission, HackathonRegistration
4+
5+
# Register your models here.
6+
7+
admin.site.register(Hackathon)
8+
admin.site.register(Submission)
9+
admin.site.register(HackathonRegistration)

api/apps.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ApiConfig(AppConfig):
5+
default_auto_field = 'django.db.models.BigAutoField'
6+
name = 'api'

api/migrations/0001_initial.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Generated by Django 4.2.4 on 2023-08-02 09:42
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
initial = True
10+
11+
dependencies = [
12+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name='Enrollment',
18+
fields=[
19+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20+
('enrollment_date', models.DateTimeField(auto_now_add=True)),
21+
],
22+
),
23+
migrations.CreateModel(
24+
name='Hackathon',
25+
fields=[
26+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27+
('title', models.CharField(max_length=255)),
28+
('description', models.TextField()),
29+
('background_image', models.ImageField(upload_to='hackathon_images/')),
30+
('hackathon_image', models.ImageField(upload_to='hackathon_images/')),
31+
('submission_type',
32+
models.CharField(choices=[('image', 'Image'), ('file', 'File'), ('link', 'Link')], max_length=10)),
33+
('start_datetime', models.DateTimeField()),
34+
('end_datetime', models.DateTimeField()),
35+
('reward_prize', models.DecimalField(decimal_places=2, max_digits=10)),
36+
('enrolled_users', models.ManyToManyField(related_name='enrolled_hackathons', through='api.Enrollment',
37+
to=settings.AUTH_USER_MODEL)),
38+
],
39+
),
40+
migrations.CreateModel(
41+
name='Submission',
42+
fields=[
43+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
44+
('name', models.CharField(max_length=255)),
45+
('summary', models.TextField()),
46+
('image_submission', models.ImageField(blank=True, null=True, upload_to='submission_images/')),
47+
('file_submission', models.FileField(blank=True, null=True, upload_to='submission_files/')),
48+
('link_submission', models.URLField(blank=True, max_length=255, null=True)),
49+
('hackathon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions',
50+
to='api.hackathon')),
51+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
52+
],
53+
),
54+
migrations.AddField(
55+
model_name='enrollment',
56+
name='hackathon',
57+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.hackathon'),
58+
),
59+
migrations.AddField(
60+
model_name='enrollment',
61+
name='user',
62+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
63+
),
64+
migrations.AlterUniqueTogether(
65+
name='enrollment',
66+
unique_together={('user', 'hackathon')},
67+
),
68+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 4.2.4 on 2023-08-02 10:14
2+
3+
import django.db.models.deletion
4+
from django.conf import settings
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
dependencies = [
10+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11+
('api', '0001_initial'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='HackathonRegistration',
17+
fields=[
18+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('registration_date', models.DateTimeField(auto_now_add=True)),
20+
('hackathon', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='api.hackathon')),
21+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
22+
],
23+
),
24+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Generated by Django 4.2.4 on 2023-08-02 14:10
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
10+
('api', '0002_hackathonregistration'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='hackathon',
16+
name='enrolled_users',
17+
field=models.ManyToManyField(related_name='enrolled_hackathons', through='api.HackathonRegistration',
18+
to=settings.AUTH_USER_MODEL),
19+
),
20+
migrations.AlterUniqueTogether(
21+
name='submission',
22+
unique_together={('user', 'hackathon')},
23+
),
24+
migrations.DeleteModel(
25+
name='Enrollment',
26+
),
27+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Django 4.2.4 on 2023-08-02 15:47
2+
3+
from django.conf import settings
4+
from django.db import migrations
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11+
('api', '0003_alter_hackathon_enrolled_users_and_more'),
12+
]
13+
14+
operations = [
15+
migrations.AlterUniqueTogether(
16+
name='hackathonregistration',
17+
unique_together={('user', 'hackathon')},
18+
),
19+
]

api/migrations/__init__.py

Whitespace-only changes.

api/models.py

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from django.contrib.auth.models import User
2+
from django.db import models
3+
4+
5+
class Hackathon(models.Model):
6+
SUBMISSION_CHOICES = (
7+
('image', 'Image'),
8+
('file', 'File'),
9+
('link', 'Link'),
10+
)
11+
12+
title = models.CharField(max_length=255)
13+
description = models.TextField()
14+
background_image = models.ImageField(upload_to='hackathon_images/')
15+
hackathon_image = models.ImageField(upload_to='hackathon_images/')
16+
submission_type = models.CharField(max_length=10, choices=SUBMISSION_CHOICES)
17+
start_datetime = models.DateTimeField()
18+
end_datetime = models.DateTimeField()
19+
reward_prize = models.DecimalField(max_digits=10, decimal_places=2)
20+
enrolled_users = models.ManyToManyField(User, through='HackathonRegistration', related_name='enrolled_hackathons')
21+
22+
def __str__(self):
23+
return self.title
24+
25+
26+
class Submission(models.Model):
27+
hackathon = models.ForeignKey(Hackathon, on_delete=models.CASCADE, related_name='submissions')
28+
user = models.ForeignKey(User, on_delete=models.CASCADE)
29+
name = models.CharField(max_length=255)
30+
summary = models.TextField()
31+
32+
# Add specific fields for each submission type (image, file, link)
33+
image_submission = models.ImageField(upload_to='submission_images/', blank=True, null=True)
34+
file_submission = models.FileField(upload_to='submission_files/', blank=True, null=True)
35+
link_submission = models.URLField(max_length=255, blank=True, null=True)
36+
37+
class Meta:
38+
unique_together = ['user', 'hackathon']
39+
40+
def __str__(self):
41+
return self.name
42+
43+
44+
# submissions/models.py
45+
46+
class HackathonRegistration(models.Model):
47+
user = models.ForeignKey(User, on_delete=models.CASCADE)
48+
hackathon = models.ForeignKey(Hackathon, on_delete=models.CASCADE)
49+
registration_date = models.DateTimeField(auto_now_add=True)
50+
51+
class Meta:
52+
unique_together = ['user', 'hackathon']
53+
54+
55+
def __str__(self):
56+
return f"{self.user.username} registered for {self.hackathon.title}"

api/serializers.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
from django.contrib.auth.models import User
2+
from rest_framework import serializers
3+
4+
from api.models import Submission, Hackathon, HackathonRegistration
5+
6+
7+
class UserRegistrationSerializer(serializers.ModelSerializer):
8+
password = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'})
9+
10+
class Meta:
11+
model = User
12+
fields = ['username', 'password']
13+
14+
def create(self, validated_data):
15+
user = User.objects.create_user(
16+
username=validated_data['username'],
17+
password=validated_data['password']
18+
)
19+
return user
20+
21+
22+
class SubmissionSerializer(serializers.ModelSerializer):
23+
class Meta:
24+
model = Submission
25+
fields = '__all__'
26+
extra_kwargs = {
27+
'user': {
28+
'read_only': True,
29+
},
30+
'hackathon': {
31+
'read_only': True,
32+
},
33+
}
34+
35+
def create(self, validated_data):
36+
user = self.context['request'].user
37+
hackathon = validated_data['hackathon']
38+
39+
# Check if the user is registered for the hackathon
40+
if not HackathonRegistration.objects.filter(user=user, hackathon=hackathon).exists():
41+
raise serializers.ValidationError("You are not registered for this hackathon.")
42+
43+
submission = Submission.objects.create(**validated_data)
44+
return submission
45+
46+
def to_representation(self, instance):
47+
representation = super().to_representation(instance)
48+
hackathon = instance.hackathon
49+
submission_type = hackathon.submission_type
50+
representation['user'] = instance.user.username
51+
representation['hackathon'] = instance.hackathon.title
52+
53+
if submission_type == 'image':
54+
representation.pop('file_submission', None)
55+
representation.pop('link_submission', None)
56+
elif submission_type == 'file':
57+
representation.pop('image_submission', None)
58+
representation.pop('link_submission', None)
59+
elif submission_type == 'link':
60+
representation.pop('image_submission', None)
61+
representation.pop('file_submission', None)
62+
63+
return representation
64+
65+
def validate(self, data):
66+
hackathon = self.context['view'].get_object()
67+
submission_type = hackathon.submission_type
68+
69+
if submission_type == 'image':
70+
if not data.get('image_submission'):
71+
raise serializers.ValidationError("Image submission is required.")
72+
data.pop('file_submission', None)
73+
data.pop('link_submission', None)
74+
elif submission_type == 'file':
75+
if not data.get('file_submission'):
76+
raise serializers.ValidationError("File submission is required.")
77+
data.pop('image_submission', None)
78+
data.pop('link_submission', None)
79+
elif submission_type == 'link':
80+
if not data.get('link_submission'):
81+
raise serializers.ValidationError("Link submission is required.")
82+
data.pop('image_submission', None)
83+
data.pop('file_submission', None)
84+
85+
return data
86+
87+
88+
89+
class UserSerializer(serializers.ModelSerializer):
90+
class Meta:
91+
model = User
92+
fields = ['id', 'username']
93+
94+
95+
class HackathonSerializer(serializers.ModelSerializer):
96+
submissions = SubmissionSerializer(many=True, read_only=True)
97+
registrations = serializers.SerializerMethodField()
98+
submission_count = serializers.SerializerMethodField()
99+
100+
class Meta:
101+
model = Hackathon
102+
fields = '__all__'
103+
104+
def get_registrations(self, obj):
105+
return obj.hackathonregistration_set.count()
106+
107+
def get_submission_count(self, obj):
108+
user = self.context['request'].user
109+
return Submission.objects.filter(user=user, hackathon=obj).count()
110+
111+
112+
class HackathonRegistrationSerializer(serializers.ModelSerializer):
113+
class Meta:
114+
model = HackathonRegistration
115+
fields = '__all__'
116+
extra_kwargs = {
117+
'user': {
118+
'read_only': True,
119+
},
120+
}

api/tests.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Create your tests here.

api/urls.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from django.urls import path
2+
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
3+
4+
from .views import (
5+
UserRegistrationView,
6+
HackathonListCreateView,
7+
HackathonDetailView,
8+
EnrolledHackathonListView,
9+
UserSubmissionInView,
10+
HackathonRegistrationView, HackathonSubmissionView,
11+
)
12+
13+
urlpatterns = [
14+
# Your other URL patterns
15+
path('register/', UserRegistrationView.as_view(), name='user_registration'),
16+
path('login/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
17+
path('login/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
18+
path('hackathons/', HackathonListCreateView.as_view(), name='hackathon-list-create'),
19+
path('hackathons/<int:pk>/', HackathonDetailView.as_view(), name='hackathon-detail'),
20+
path('hackathons/register/', HackathonRegistrationView.as_view(), name='hackathon_registration'),
21+
path('hackathons/<int:pk>/submission/', HackathonSubmissionView.as_view(), name='hackathon_submission'),
22+
path('registered-hackathons/', EnrolledHackathonListView.as_view(), name='register-hackathon-list'),
23+
path('registered-hackathons/<int:pk>/submission/', UserSubmissionInView.as_view(),name='user-submission-in-hackathon'),
24+
25+
]

0 commit comments

Comments
 (0)