├── .gitignore
├── README.md
├── accounts
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── managers.py
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── models.py
├── templates
│ └── accounts
│ │ ├── login.html
│ │ └── register.html
├── tests.py
├── urls.py
└── views.py
├── common
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
├── events
├── __init__.py
├── admin.py
├── apps.py
├── forms.py
├── migrations
│ ├── 0001_initial.py
│ ├── 0002_idea.py
│ ├── 0003_ideaupvote.py
│ └── __init__.py
├── models.py
├── templates
│ └── events
│ │ └── event_detail.html
├── tests.py
├── urls.py
└── views.py
├── hackogi
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
├── views.py
└── wsgi.py
├── manage.py
└── templates
├── base.html
├── header.html
└── home.html
/.gitignore:
--------------------------------------------------------------------------------
1 | venv
2 | db.sqlite3
3 | **/__pycache__/
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hackathon Management Platform
2 |
3 | By https://t.me/JR_TwitGram
4 |
--------------------------------------------------------------------------------
/accounts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/accounts/__init__.py
--------------------------------------------------------------------------------
/accounts/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
3 | from django.contrib.auth import get_user_model
4 |
5 |
6 | User = get_user_model()
7 |
8 |
9 | class UserAdmin(DjangoUserAdmin):
10 | ordering = ("pk",)
11 | list_display = (
12 | "email",
13 | "first_name",
14 | "last_name",
15 | "is_staff",
16 | "is_active",
17 | )
18 |
19 |
20 | admin.site.register(User, UserAdmin)
21 |
--------------------------------------------------------------------------------
/accounts/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AccountsConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "accounts"
7 |
--------------------------------------------------------------------------------
/accounts/forms.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
2 | from django.forms import TextInput, EmailInput, PasswordInput
3 | from accounts.models import CustomUser
4 |
5 |
6 | class CustomLoginForm(AuthenticationForm):
7 | def __init__(self, *args, **kwargs):
8 | super(CustomLoginForm, self).__init__(*args, **kwargs)
9 | self.fields['username'].widget = TextInput(attrs={
10 | 'class': 'form-control',
11 | 'placeholder': 'Enter Your Username'
12 | })
13 | self.fields['password'].widget = PasswordInput(attrs={
14 | 'class': 'form-control',
15 | 'placeholder': 'Enter Your Password'
16 | })
17 |
18 | class RegisterForm(UserCreationForm):
19 | def __init__(self, *args, **kwargs):
20 | super(RegisterForm, self).__init__(*args, **kwargs)
21 | self.fields['email'].widget = EmailInput(attrs={
22 | 'class': 'form-control',
23 | 'placeholder': 'Enter Your Email'
24 | })
25 | self.fields['password1'].widget = PasswordInput(attrs={
26 | 'class': 'form-control',
27 | 'placeholder': 'Enter Your Password',
28 | 'id': 'password1'
29 | })
30 | self.fields['password2'].widget = PasswordInput(attrs={
31 | 'class': 'form-control',
32 | 'placeholder': 'Enter Your Password Confirmation',
33 | 'id': 'password2'
34 | })
35 |
36 | class Meta:
37 | model = CustomUser
38 | fields = (
39 | "email",
40 | "password1",
41 | "password2"
42 | )
43 |
--------------------------------------------------------------------------------
/accounts/managers.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.base_user import BaseUserManager
2 | from django.utils.translation import gettext_lazy as _
3 |
4 |
5 | class CustomUserManager(BaseUserManager):
6 | """
7 | Custom user model manager where email is the unique identifiers
8 | for authentication instead of usernames.
9 | """
10 | def create_user(self, email, password, **extra_fields):
11 | """
12 | Create and save a user with the given email and password.
13 | """
14 | if not email:
15 | raise ValueError(_("The Email must be set"))
16 | email = self.normalize_email(email)
17 | user = self.model(email=email, **extra_fields)
18 | user.set_password(password)
19 | user.save()
20 | return user
21 |
22 | def create_superuser(self, email, password, **extra_fields):
23 | """
24 | Create and save a SuperUser with the given email and password.
25 | """
26 | extra_fields.setdefault("is_staff", True)
27 | extra_fields.setdefault("is_superuser", True)
28 | extra_fields.setdefault("is_active", True)
29 |
30 | if extra_fields.get("is_staff") is not True:
31 | raise ValueError(_("Superuser must have is_staff=True."))
32 | if extra_fields.get("is_superuser") is not True:
33 | raise ValueError(_("Superuser must have is_superuser=True."))
34 | return self.create_user(email, password, **extra_fields)
35 |
36 |
--------------------------------------------------------------------------------
/accounts/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.0.6 on 2024-06-16 11:15
2 |
3 | import django.utils.timezone
4 | from django.db import migrations, models
5 |
6 |
7 | class Migration(migrations.Migration):
8 |
9 | initial = True
10 |
11 | dependencies = [
12 | ("auth", "0012_alter_user_first_name_max_length"),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name="CustomUser",
18 | fields=[
19 | (
20 | "id",
21 | models.BigAutoField(
22 | auto_created=True,
23 | primary_key=True,
24 | serialize=False,
25 | verbose_name="ID",
26 | ),
27 | ),
28 | ("password", models.CharField(max_length=128, verbose_name="password")),
29 | (
30 | "last_login",
31 | models.DateTimeField(
32 | blank=True, null=True, verbose_name="last login"
33 | ),
34 | ),
35 | (
36 | "is_superuser",
37 | models.BooleanField(
38 | default=False,
39 | help_text="Designates that this user has all permissions without explicitly assigning them.",
40 | verbose_name="superuser status",
41 | ),
42 | ),
43 | (
44 | "email",
45 | models.EmailField(
46 | max_length=254, unique=True, verbose_name="email address"
47 | ),
48 | ),
49 | (
50 | "first_name",
51 | models.CharField(max_length=150, verbose_name="first name"),
52 | ),
53 | (
54 | "last_name",
55 | models.CharField(max_length=150, verbose_name="last name"),
56 | ),
57 | ("is_staff", models.BooleanField(default=False)),
58 | ("is_active", models.BooleanField(default=True)),
59 | (
60 | "date_joined",
61 | models.DateTimeField(default=django.utils.timezone.now),
62 | ),
63 | (
64 | "groups",
65 | models.ManyToManyField(
66 | blank=True,
67 | help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
68 | related_name="user_set",
69 | related_query_name="user",
70 | to="auth.group",
71 | verbose_name="groups",
72 | ),
73 | ),
74 | (
75 | "user_permissions",
76 | models.ManyToManyField(
77 | blank=True,
78 | help_text="Specific permissions for this user.",
79 | related_name="user_set",
80 | related_query_name="user",
81 | to="auth.permission",
82 | verbose_name="user permissions",
83 | ),
84 | ),
85 | ],
86 | options={
87 | "verbose_name": "User",
88 | "verbose_name_plural": "Users",
89 | },
90 | ),
91 | ]
92 |
--------------------------------------------------------------------------------
/accounts/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/accounts/migrations/__init__.py
--------------------------------------------------------------------------------
/accounts/models.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
2 | from django.db import models
3 | from django.utils import timezone
4 | from django.utils.translation import gettext_lazy as _
5 |
6 | from accounts.managers import CustomUserManager
7 | from events.models import IdeaUpvote
8 |
9 |
10 | class CustomUser(AbstractBaseUser, PermissionsMixin):
11 | email = models.EmailField(_("email address"), unique=True)
12 |
13 | first_name = models.CharField(_("first name"), max_length=150)
14 | last_name = models.CharField(_("last name"), max_length=150)
15 |
16 | is_staff = models.BooleanField(default=False)
17 | is_active = models.BooleanField(default=True)
18 |
19 | date_joined = models.DateTimeField(default=timezone.now)
20 |
21 | USERNAME_FIELD = "email"
22 | REQUIRED_FIELDS = ["first_name", "last_name"]
23 |
24 | objects = CustomUserManager()
25 |
26 | class Meta:
27 | verbose_name = _("User")
28 | verbose_name_plural = _("Users")
29 |
30 | def __str__(self):
31 | return f"{self.first_name} {self.last_name}"
32 |
33 | def likes_idea(self, idea_id):
34 | return IdeaUpvote.objects.filter(user=self, idea_id=idea_id)
35 |
--------------------------------------------------------------------------------
/accounts/templates/accounts/login.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %} Login Page {% endblock title %}
4 |
5 | {% block content %}
6 |
7 |
8 |
9 |
10 |
11 |

13 |
14 |
44 |
45 |
46 |
47 | {% endblock content %}
--------------------------------------------------------------------------------
/accounts/templates/accounts/register.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block title %} Register Page {% endblock title %}
4 |
5 | {% block content %}
6 |
12 |
49 |
50 |
51 |
92 | {% endblock content %}
--------------------------------------------------------------------------------
/accounts/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/accounts/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | from accounts.views import LoginView, logout_view, RegisterView
4 |
5 | app_name = "accounts"
6 | urlpatterns = [
7 | path("register/", RegisterView.as_view(), name="register"),
8 | path("login/", LoginView.as_view(), name="login"),
9 | path("logout/", logout_view, name="logout-view"),
10 | ]
11 |
12 |
--------------------------------------------------------------------------------
/accounts/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import authenticate, login, logout
2 | from django.shortcuts import render, redirect
3 | from django.views import View
4 |
5 | from accounts.forms import CustomLoginForm, RegisterForm
6 |
7 |
8 | class RegisterView(View):
9 | def get(self, request):
10 | form = RegisterForm()
11 | return render(request, "accounts/register.html", context={"form": form})
12 |
13 | def post(self, request):
14 | form = RegisterForm(request.POST)
15 | if form.is_valid():
16 | form.save()
17 | return redirect("accounts:login")
18 | return render(request, "accounts/register.html", context={"form": form})
19 |
20 |
21 | class LoginView(View):
22 | def get(self, request):
23 | form = CustomLoginForm()
24 | return render(request, "accounts/login.html", context={"form": form})
25 |
26 | def post(self, request):
27 | form = CustomLoginForm(request, request.POST)
28 |
29 | if form.is_valid():
30 | username = form.cleaned_data["username"]
31 | password = form.cleaned_data["password"]
32 | user = authenticate(request, username=username, password=password)
33 |
34 | if user:
35 | login(request, user)
36 | return redirect("home")
37 |
38 | return render(request, "accounts/login.html", context={"form": form})
39 |
40 | def logout_view(request):
41 | logout(request)
42 | return redirect("home")
43 |
--------------------------------------------------------------------------------
/common/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/common/__init__.py
--------------------------------------------------------------------------------
/common/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/common/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CommonConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "common"
7 |
--------------------------------------------------------------------------------
/common/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/common/migrations/__init__.py
--------------------------------------------------------------------------------
/common/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | class BaseModel(models.Model):
4 | created_at = models.DateTimeField(auto_now_add=True)
5 | updated_at = models.DateTimeField(auto_now=True)
6 |
7 | class Meta:
8 | abstract = True
9 |
10 |
--------------------------------------------------------------------------------
/common/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/common/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/events/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/events/__init__.py
--------------------------------------------------------------------------------
/events/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | from .models import Event, Idea, IdeaUpvote
4 |
5 |
6 | class EventAdmin(admin.ModelAdmin):
7 | list_display = (
8 | "title",
9 | "organizer",
10 | "start_date",
11 | "end_date",
12 | "is_approved",
13 | )
14 |
15 |
16 | class IdeaAdmin(admin.ModelAdmin):
17 | pass
18 |
19 | class IdeaUpvoteAdmin(admin.ModelAdmin):
20 | pass
21 |
22 | admin.site.register(Event, EventAdmin)
23 | admin.site.register(Idea, IdeaAdmin)
24 | admin.site.register(IdeaUpvote, IdeaUpvoteAdmin)
25 |
--------------------------------------------------------------------------------
/events/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class EventsConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "events"
7 |
--------------------------------------------------------------------------------
/events/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 |
3 | from events.models import Idea
4 |
5 |
6 | class CreateIdeaForm(forms.ModelForm):
7 | class Meta:
8 | model = Idea
9 | fields = (
10 | "title",
11 | "overview",
12 | )
13 |
14 | def __init__(self, *args, **kwargs):
15 | super().__init__(*args, **kwargs)
16 | self.fields['title'].widget = forms.TextInput(attrs={
17 | 'class': 'form-control',
18 | 'placeholder': 'Idea Title'
19 | })
20 | self.fields['overview'].widget = forms.Textarea(attrs={
21 | 'class': 'form-control',
22 | 'placeholder': 'Idea Overview'
23 | })
24 |
--------------------------------------------------------------------------------
/events/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.0.6 on 2024-06-16 11:46
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 |
10 | initial = True
11 |
12 | dependencies = [
13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14 | ]
15 |
16 | operations = [
17 | migrations.CreateModel(
18 | name="Event",
19 | fields=[
20 | (
21 | "id",
22 | models.BigAutoField(
23 | auto_created=True,
24 | primary_key=True,
25 | serialize=False,
26 | verbose_name="ID",
27 | ),
28 | ),
29 | ("created_at", models.DateTimeField(auto_now_add=True)),
30 | ("updated_at", models.DateTimeField(auto_now=True)),
31 | ("title", models.CharField(max_length=255, verbose_name="title")),
32 | ("overview", models.TextField(verbose_name="overview")),
33 | ("start_date", models.DateTimeField(verbose_name="start date")),
34 | ("end_date", models.DateTimeField(verbose_name="end date")),
35 | ("is_approved", models.BooleanField(default=False)),
36 | (
37 | "organizer",
38 | models.ForeignKey(
39 | on_delete=django.db.models.deletion.CASCADE,
40 | related_name="events",
41 | related_query_name="event",
42 | to=settings.AUTH_USER_MODEL,
43 | ),
44 | ),
45 | ],
46 | options={
47 | "abstract": False,
48 | },
49 | ),
50 | ]
51 |
--------------------------------------------------------------------------------
/events/migrations/0002_idea.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.0.6 on 2024-07-07 08:50
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 |
10 | dependencies = [
11 | ("events", "0001_initial"),
12 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name="Idea",
18 | fields=[
19 | (
20 | "id",
21 | models.BigAutoField(
22 | auto_created=True,
23 | primary_key=True,
24 | serialize=False,
25 | verbose_name="ID",
26 | ),
27 | ),
28 | ("created_at", models.DateTimeField(auto_now_add=True)),
29 | ("updated_at", models.DateTimeField(auto_now=True)),
30 | ("title", models.CharField(max_length=255, verbose_name="title")),
31 | ("overview", models.TextField(verbose_name="overview")),
32 | (
33 | "event",
34 | models.ForeignKey(
35 | on_delete=django.db.models.deletion.CASCADE,
36 | related_name="ideas",
37 | related_query_name="idea",
38 | to="events.event",
39 | ),
40 | ),
41 | (
42 | "owner",
43 | models.ForeignKey(
44 | on_delete=django.db.models.deletion.CASCADE,
45 | related_name="ideas",
46 | related_query_name="idea",
47 | to=settings.AUTH_USER_MODEL,
48 | ),
49 | ),
50 | ],
51 | options={
52 | "abstract": False,
53 | },
54 | ),
55 | ]
56 |
--------------------------------------------------------------------------------
/events/migrations/0003_ideaupvote.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 5.0.6 on 2024-07-07 10:04
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 |
10 | dependencies = [
11 | ("events", "0002_idea"),
12 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
13 | ]
14 |
15 | operations = [
16 | migrations.CreateModel(
17 | name="IdeaUpvote",
18 | fields=[
19 | (
20 | "id",
21 | models.BigAutoField(
22 | auto_created=True,
23 | primary_key=True,
24 | serialize=False,
25 | verbose_name="ID",
26 | ),
27 | ),
28 | ("created_at", models.DateTimeField(auto_now_add=True)),
29 | ("updated_at", models.DateTimeField(auto_now=True)),
30 | (
31 | "idea",
32 | models.ForeignKey(
33 | on_delete=django.db.models.deletion.CASCADE,
34 | related_name="upvotes",
35 | related_query_name="upvote",
36 | to="events.idea",
37 | ),
38 | ),
39 | (
40 | "user",
41 | models.ForeignKey(
42 | on_delete=django.db.models.deletion.CASCADE,
43 | related_name="upvotes",
44 | related_query_name="upvote",
45 | to=settings.AUTH_USER_MODEL,
46 | ),
47 | ),
48 | ],
49 | options={
50 | "unique_together": {("idea", "user")},
51 | },
52 | ),
53 | ]
54 |
--------------------------------------------------------------------------------
/events/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/events/migrations/__init__.py
--------------------------------------------------------------------------------
/events/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.utils.translation import gettext_lazy as _
3 |
4 | from common.models import BaseModel
5 |
6 |
7 | class Event(BaseModel):
8 | organizer = models.ForeignKey(
9 | "accounts.CustomUser",
10 | on_delete=models.CASCADE,
11 | related_name="events",
12 | related_query_name="event",
13 | )
14 |
15 | title = models.CharField(_("title"), max_length=255)
16 | overview = models.TextField(_("overview"))
17 |
18 | start_date = models.DateTimeField(_("start date"))
19 | end_date = models.DateTimeField(_("end date"))
20 |
21 | is_approved = models.BooleanField(default=False)
22 |
23 | def __str__(self):
24 | return self.title
25 |
26 |
27 | class Idea(BaseModel):
28 | event = models.ForeignKey(
29 | Event, related_name="ideas", related_query_name="idea", on_delete=models.CASCADE
30 | )
31 | owner = models.ForeignKey(
32 | "accounts.CustomUser",
33 | related_name="ideas",
34 | related_query_name="idea",
35 | on_delete=models.CASCADE,
36 | )
37 | title = models.CharField(_("title"), max_length=255)
38 | overview = models.TextField(_("overview"))
39 |
40 | def __str__(self):
41 | return self.title
42 |
43 |
44 | class IdeaUpvote(BaseModel):
45 | idea = models.ForeignKey(
46 | Idea,
47 | related_name="upvotes",
48 | related_query_name="upvote",
49 | on_delete=models.CASCADE,
50 | )
51 | user = models.ForeignKey(
52 | "accounts.CustomUser",
53 | related_name="upvotes",
54 | related_query_name="upvote",
55 | on_delete=models.CASCADE,
56 | )
57 |
58 | class Meta:
59 | unique_together = ("idea", "user",)
60 |
61 | def __str__(self):
62 | return f"{self.user} likes {self.idea.title}"
63 |
--------------------------------------------------------------------------------
/events/templates/events/event_detail.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% block title %} Event Detail Page {% endblock title %}
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
9 |

11 |
12 |
13 |
{{ event.title }}
14 |
25 |
26 |
27 |
28 |
29 |
30 | {{ event.overview }}
31 |
32 |
33 | {% if request.user.is_authenticated %}
34 |
35 |
51 |
52 | {% endif %}
53 |
54 | {% for idea in ideas %}
55 |
56 |
59 |
60 |
61 |
62 |
{{ idea.title }}
63 | {% if idea.is_liked %}
64 |
65 | {% else %}
66 |
67 | {% endif %}
68 |
{{ idea.upvotes.count }}
69 |
{{ idea.overview }}
70 |
71 |
72 |
73 |
74 | {% endfor %}
75 |
76 |
...
77 |
78 |
79 |
80 |
85 | {% endblock %}
86 |
--------------------------------------------------------------------------------
/events/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/events/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | from events.views import EventDetailView, CreateEventIdeaView, UpvoteIdeaView
4 |
5 | app_name = "events"
6 | urlpatterns = [
7 | path("/", EventDetailView.as_view(), name="event-detail"),
8 | path("/ideas/", CreateEventIdeaView.as_view(), name="create-idea"),
9 | path("/ideas//", UpvoteIdeaView.as_view(), name="upvote-idea"),
10 | ]
11 |
--------------------------------------------------------------------------------
/events/views.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.mixins import LoginRequiredMixin
2 | from django.db.models import Exists, OuterRef
3 | from django.http.response import HttpResponse
4 | from django.shortcuts import redirect, render
5 | from django.views import View
6 |
7 | from events.forms import CreateIdeaForm
8 | from events.models import Event, Idea, IdeaUpvote
9 |
10 |
11 | class EventDetailView(View):
12 | def get(self, request, event_id):
13 | try:
14 | event = Event.objects.get(pk=event_id)
15 | except Event.DoesNotExist:
16 | return HttpResponse("Event does not exist")
17 |
18 | ideas = event.ideas.annotate(
19 | is_liked=Exists(
20 | IdeaUpvote.objects.filter(user=request.user, idea=OuterRef("pk"))
21 | )
22 | )
23 | context = {"event": event, "idea_form": CreateIdeaForm(), "ideas": ideas}
24 |
25 | return render(request, "events/event_detail.html", context=context)
26 |
27 |
28 | class CreateEventIdeaView(LoginRequiredMixin, View):
29 | def post(self, request, event_id):
30 | try:
31 | event = Event.objects.get(pk=event_id)
32 | except Event.DoesNotExist:
33 | return HttpResponse("Event does not exist")
34 |
35 | form = CreateIdeaForm(request.POST)
36 |
37 | if form.is_valid():
38 | Idea.objects.create(
39 | owner=request.user,
40 | event=event,
41 | title=form.cleaned_data["title"],
42 | overview=form.cleaned_data["overview"],
43 | )
44 |
45 | return redirect("events:event-detail", event_id=event.id)
46 |
47 |
48 | class UpvoteIdeaView(LoginRequiredMixin, View):
49 | def post(self, request, event_id, idea_id):
50 | try:
51 | idea = Idea.objects.get(id=idea_id, event__id=event_id)
52 | except Idea.DoesNotExist:
53 | return HttpResponse("Idea does not exist")
54 |
55 | IdeaUpvote.objects.create(idea=idea, user=request.user)
56 |
57 | return redirect("events:event-detail", event_id=event_id)
58 |
--------------------------------------------------------------------------------
/hackogi/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rahmonov/hackogi/c272e7d323df6b88b4e070d361565565414e580e/hackogi/__init__.py
--------------------------------------------------------------------------------
/hackogi/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for hackogi project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hackogi.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/hackogi/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for hackogi project.
3 |
4 | Generated by 'django-admin startproject' using Django 5.0.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/5.0/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/5.0/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'django-insecure-_6h(2&47$x*k&b^vb($p@y^57pkz1(60ab+l%g+h@kj#!g1mjk'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 | AUTH_USER_MODEL = "accounts.CustomUser"
31 |
32 | # Application definition
33 |
34 | INSTALLED_APPS = [
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | "accounts",
42 | "common",
43 | "events",
44 | ]
45 |
46 | MIDDLEWARE = [
47 | 'django.middleware.security.SecurityMiddleware',
48 | 'django.contrib.sessions.middleware.SessionMiddleware',
49 | 'django.middleware.common.CommonMiddleware',
50 | 'django.middleware.csrf.CsrfViewMiddleware',
51 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
52 | 'django.contrib.messages.middleware.MessageMiddleware',
53 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
54 | ]
55 |
56 | ROOT_URLCONF = 'hackogi.urls'
57 |
58 | TEMPLATES = [
59 | {
60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
61 | 'DIRS': [(BASE_DIR / 'templates')],
62 | 'APP_DIRS': True,
63 | 'OPTIONS': {
64 | 'context_processors': [
65 | 'django.template.context_processors.debug',
66 | 'django.template.context_processors.request',
67 | 'django.contrib.auth.context_processors.auth',
68 | 'django.contrib.messages.context_processors.messages',
69 | ],
70 | },
71 | },
72 | ]
73 |
74 | WSGI_APPLICATION = 'hackogi.wsgi.application'
75 |
76 |
77 | # Database
78 | # https://docs.djangoproject.com/en/5.0/ref/settings/#databases
79 |
80 | DATABASES = {
81 | 'default': {
82 | 'ENGINE': 'django.db.backends.sqlite3',
83 | 'NAME': BASE_DIR / 'db.sqlite3',
84 | }
85 | }
86 |
87 |
88 | # Password validation
89 | # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
90 |
91 | AUTH_PASSWORD_VALIDATORS = [
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
103 | },
104 | ]
105 |
106 |
107 | # Internationalization
108 | # https://docs.djangoproject.com/en/5.0/topics/i18n/
109 |
110 | LANGUAGE_CODE = 'en-us'
111 |
112 | TIME_ZONE = 'UTC'
113 |
114 | USE_I18N = True
115 |
116 | USE_TZ = True
117 |
118 |
119 | # Static files (CSS, JavaScript, Images)
120 | # https://docs.djangoproject.com/en/5.0/howto/static-files/
121 |
122 | STATIC_URL = 'static/'
123 |
124 | # Default primary key field type
125 | # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
126 |
127 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
128 |
--------------------------------------------------------------------------------
/hackogi/urls.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 | from django.urls import path, include
3 |
4 | from hackogi.views import home_page
5 |
6 | urlpatterns = [
7 | path("", home_page, name="home"),
8 | path("events/", include("events.urls", namespace="events")),
9 | path("accounts/", include("accounts.urls", namespace="accounts")),
10 | path('admin/', admin.site.urls),
11 | ]
12 |
--------------------------------------------------------------------------------
/hackogi/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from django.utils import timezone
3 |
4 | from events.models import Event
5 |
6 |
7 | def home_page(request):
8 | now = timezone.now()
9 | active_hackathons = Event.objects.filter(
10 | is_approved=True, start_date__lt=now, end_date__gt=now
11 | )
12 | past_hackathons = Event.objects.filter(is_approved=True, end_date__lt=now)
13 | upcoming_hackathons = Event.objects.filter(is_approved=True, start_date__gt=now)
14 |
15 | return render(
16 | request,
17 | "home.html",
18 | context={
19 | "active_hackathons": active_hackathons,
20 | "upcoming_hackathons": upcoming_hackathons,
21 | "past_hackathons": past_hackathons,
22 | },
23 | )
24 |
--------------------------------------------------------------------------------
/hackogi/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for hackogi project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hackogi.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hackogi.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {% block title %}{% endblock title %}
5 |
6 |
7 |
8 |
9 |
10 | {% include "header.html" %}
11 |
12 | {% block content %}{% endblock content %}
13 |
14 |
15 |
16 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/templates/header.html:
--------------------------------------------------------------------------------
1 |
32 |
--------------------------------------------------------------------------------
/templates/home.html:
--------------------------------------------------------------------------------
1 | {% extends 'base.html' %}
2 | {% block title %} Home Page {% endblock title %}
3 |
4 | {% block content %}
5 |
6 |
7 |
8 |
Title of a longer featured blog post
9 |
Multiple lines of text that form the lede, informing new readers quickly and efficiently
10 | about what’s most interesting in this post’s contents.
11 |
Continue reading...
12 |
13 |
14 |
15 | Active Hackathons
16 |
17 | {% for hackathon in active_hackathons %}
18 |
37 | {% endfor %}
38 |
39 |
40 | Upcoming Hackathons
41 |
42 | {% for hackathon in upcoming_hackathons %}
43 |
62 | {% endfor %}
63 |
64 |
65 | Past Hackathons
66 |
67 | {% for hackathon in past_hackathons %}
68 |
87 | {% endfor %}
88 |
89 |
90 |
91 | {% endblock %}
92 |
--------------------------------------------------------------------------------