From cc342564e85e0ebd7d1432504aa096c5546bb25b Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 12:58:19 -0400 Subject: [PATCH 1/8] Add Pillow library to support Django ImageField --- Pipfile | 1 + Pipfile.lock | 80 +++++++++++++++++++++++++++++++++++++++++++- requirements-dev.txt | 1 + requirements.txt | 1 + 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/Pipfile b/Pipfile index 0e4cc09..4b631d8 100644 --- a/Pipfile +++ b/Pipfile @@ -17,6 +17,7 @@ django-hashid-field = "*" django-celery-beat = "*" flower = "*" discord-py = "==2.5.0" +pillow = "*" [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 357419c..7577915 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "d94bae63abd3a5b6ef5877241a4a1b29af21cf2b07471fcddae3a5225a533974" + "sha256": "551ef30ba23afe0e95563298d016a31e0eebc65afe08f6af5e972fed1c9db345" }, "pipfile-spec": 6, "requires": { @@ -757,6 +757,84 @@ "markers": "python_version >= '3.8'", "version": "==24.2" }, + "pillow": { + "hashes": [ + "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83", + "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", + "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", + "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", + "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", + "sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f", + "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", + "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", + "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", + "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49", + "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", + "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", + "sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2", + "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", + "sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884", + "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e", + "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", + "sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196", + "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", + "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", + "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269", + "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", + "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb", + "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", + "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", + "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", + "sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8", + "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90", + "sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc", + "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", + "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", + "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", + "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", + "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", + "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", + "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2", + "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", + "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", + "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65", + "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", + "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442", + "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", + "sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade", + "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482", + "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", + "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", + "sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a", + "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", + "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", + "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a", + "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07", + "sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6", + "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", + "sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e", + "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192", + "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", + "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", + "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73", + "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f", + "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", + "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", + "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", + "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", + "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8", + "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26", + "sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5", + "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", + "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", + "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", + "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", + "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==11.1.0" + }, "prometheus-client": { "hashes": [ "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb", diff --git a/requirements-dev.txt b/requirements-dev.txt index 8ebe30a..f60c613 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -33,6 +33,7 @@ kombu==5.5.0; python_version >= '3.8' multidict==6.1.0; python_version >= '3.8' mysqlclient==2.2.7; python_version >= '3.8' packaging==24.2; python_version >= '3.8' +pillow==11.1.0; python_version >= '3.9' prometheus-client==0.21.1; python_version >= '3.8' prompt-toolkit==3.0.50; python_full_version >= '3.8.0' propcache==0.3.0; python_version >= '3.9' diff --git a/requirements.txt b/requirements.txt index 8ebe30a..f60c613 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,6 +33,7 @@ kombu==5.5.0; python_version >= '3.8' multidict==6.1.0; python_version >= '3.8' mysqlclient==2.2.7; python_version >= '3.8' packaging==24.2; python_version >= '3.8' +pillow==11.1.0; python_version >= '3.9' prometheus-client==0.21.1; python_version >= '3.8' prompt-toolkit==3.0.50; python_full_version >= '3.8.0' propcache==0.3.0; python_version >= '3.9' From 6185d735c6e1914ecab995f15cbacf511e3a581d Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 12:59:39 -0400 Subject: [PATCH 2/8] Add Sponsor model in core folder --- src/core/migrations/0001_initial.py | 24 ++++++++++++++++++++++++ src/core/models.py | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/core/migrations/0001_initial.py diff --git a/src/core/migrations/0001_initial.py b/src/core/migrations/0001_initial.py new file mode 100644 index 0000000..fae81f7 --- /dev/null +++ b/src/core/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.20 on 2025-03-30 15:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Sponsor', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, unique=True)), + ('logo', models.ImageField(upload_to='sponsors')), + ('url', models.URLField(blank=True)), + ('message', models.TextField(blank=True)), + ], + ), + ] diff --git a/src/core/models.py b/src/core/models.py index 71a8362..f76119f 100644 --- a/src/core/models.py +++ b/src/core/models.py @@ -1,3 +1,25 @@ from django.db import models # Create your models here. + +class Sponsor(models.Model): + """ + Contest sponsor model. Each model stores the details of a contest sponsor, including + name, logo, link to sponsor's website, and message. + + name (CharField): the sponsor name (unique) + + logo (ImageField): the sponsor logo + + url (URLField): the sponsor URL + + message (TextField): the sponsor message + """ + + name = models.CharField(max_length=200, unique=True) + logo = models.ImageField(upload_to='sponsors') + url = models.URLField(blank=True) + message = models.TextField(blank=True) + + def __str__(self): + return self.name \ No newline at end of file From c923e56cd200cf84cd9a50b3b285114d370fbe53 Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 13:04:14 -0400 Subject: [PATCH 3/8] Add SponsorAdmin for admin interface --- src/core/admin.py | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/core/admin.py b/src/core/admin.py index ce04b43..1a5371f 100644 --- a/src/core/admin.py +++ b/src/core/admin.py @@ -1,18 +1,20 @@ from django.contrib import admin from django.contrib.auth.models import User +from django.utils.html import mark_safe +from . import models from import_export import resources from import_export.admin import ImportExportModelAdmin class UserResource(resources.ModelResource): - """ - Attach User model to Django-Import-Export - https://django-import-export.readthedocs.io/en/latest/getting_started.html#creating-a-resource - """ - class Meta: - model = User - fields = ('first_name', 'last_name', 'email', 'is_active', 'profile__checked_in') + """ + Attach User model to Django-Import-Export + https://django-import-export.readthedocs.io/en/latest/getting_started.html#creating-a-resource + """ + class Meta: + model = User + fields = ('first_name', 'last_name', 'email', 'is_active', 'profile__checked_in') class UserAdmin(ImportExportModelAdmin): @@ -20,13 +22,28 @@ class UserAdmin(ImportExportModelAdmin): Django-Import-Export resource admin intrgration https://django-import-export.readthedocs.io/en/latest/advanced_usage.html#admin-integration """ - + resource_class = UserResource list_display = ("last_name", "first_name", "username", "email", "is_active",) list_filter = ("is_active",) search_fields = ["last_name", "first_name", "username", "email"] +class SponsorAdmin(admin.ModelAdmin): + """ + Define Sponsor model interface in Django Admin. + https://docs.djangoproject.com/en/4.2/ref/contrib/admin/#modeladmin-objects + """ + + list_display = ('name', 'url', 'logo_thumbnail', 'message') + search_fields = ['name', 'message'] + + def logo_thumbnail(self, obj): + if obj.logo: + return mark_safe(f'') + return '-' + # Re-register User model for django-import-export integration admin.site.unregister(User) admin.site.register(User, UserAdmin) +admin.site.register(models.Sponsor, SponsorAdmin) From 50b78003abb28ec00c736cb228fdc1a000318e54 Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 13:05:12 -0400 Subject: [PATCH 4/8] Edit main urls.py file to support static file display --- src/contestsuite/urls.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/contestsuite/urls.py b/src/contestsuite/urls.py index cacb9dc..4d09ee9 100644 --- a/src/contestsuite/urls.py +++ b/src/contestsuite/urls.py @@ -16,6 +16,8 @@ from django.contrib import admin from django.urls import include, path +from django.conf import settings +from django.conf.urls.static import static urlpatterns = [ path('', include('core.urls')), @@ -27,4 +29,4 @@ path('lfg/', include('lfg.urls')), path('manage/', include('manager.urls')), path('register/', include('register.urls')), -] +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file From c80a71a5aafe316f455de4ba1ea63c1e31505393 Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 13:06:02 -0400 Subject: [PATCH 5/8] Edit index.html to display all sponsor objects --- src/core/templates/core/index.html | 34 +++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/core/templates/core/index.html b/src/core/templates/core/index.html index 50f0744..8a6253b 100644 --- a/src/core/templates/core/index.html +++ b/src/core/templates/core/index.html @@ -98,21 +98,35 @@

Format

-

Sponsors

+ +

Sponsors

+
- FSU CS Logo - L3Harris Logo - i2x Solutions Logo - Raymond James Logo + {% for sponsor in sponsors %} + {% if sponsor.url %} + + {% endif %} + {{ sponsor.name }} + {% if sponsor.url %} + + {% endif %} + {% endfor %}
-

Sponsors

+ +

Sponsors

+
- FSU CS Logo - L3Harris Logo - i2x Solutions Logo - Raymond James Logo + {% for sponsor in sponsors %} + {% if sponsor.url %} + + {% endif %} + {{ sponsor.name }} + {% if sponsor.url %} + + {% endif %} + {% endfor %}
From 1074d466b05fcd34f444fe1f6130524025675279 Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Sun, 30 Mar 2025 13:06:40 -0400 Subject: [PATCH 6/8] Add sponsors.html and view to display sponsors --- src/core/templates/core/sponsors.html | 33 +++++++++++++++++++++++++++ src/core/urls.py | 1 + src/core/views.py | 15 ++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 src/core/templates/core/sponsors.html diff --git a/src/core/templates/core/sponsors.html b/src/core/templates/core/sponsors.html new file mode 100644 index 0000000..34510ac --- /dev/null +++ b/src/core/templates/core/sponsors.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} +{% load static %} + +{% block section %}Sponsors{% endblock %} + +{% block content %} + +

Sponsors

+ +{% if sponsors %} +

This programming contest was made possible by...

+{% endif %} + +
+ {% for sponsor in sponsors %} +
+
+ {% if sponsor.url %} + + {% endif %} + {{ sponsor.name }} + {% if sponsor.url %} + + {% endif %} +
+

{{ sponsor.message }}

+
+ {% empty %} +

No sponsors available.

+ {% endfor %} +
+ +{% endblock %} diff --git a/src/core/urls.py b/src/core/urls.py index 4beb086..0aac2f8 100644 --- a/src/core/urls.py +++ b/src/core/urls.py @@ -7,4 +7,5 @@ path('contact/', views.ContactTemplateView.as_view(), name='contact'), path('faq/', views.FaqTemplateView.as_view(), name='faq'), path('teams/', views.TeamsTemplateView.as_view(), name='teams'), + path('sponsors/', views.SponsorsTemplateView.as_view(), name='sponsors'), ] diff --git a/src/core/views.py b/src/core/views.py index 9ed854b..1fcd70b 100644 --- a/src/core/views.py +++ b/src/core/views.py @@ -9,6 +9,7 @@ from register.models import Team from manager.models import Course, Profile from lfg.models import LFGProfile +from core.models import Sponsor # Create your views here. @@ -42,6 +43,8 @@ def get_context_data(self, **kwargs): # Get published announcements context['announcements'] = (Announcement.objects.filter(status=1)) + context['sponsors'] = Sponsor.objects.all() + # Get all courses context['courses'] = Course.objects.all() @@ -131,3 +134,15 @@ def get_context_data(self, **kwargs): context['num_faculty_participants'] = participants_set.filter(team__faculty=True).count() return context + +class SponsorsTemplateView(TemplateView): + """ + View to display sponsors page. + """ + + template_name = 'core/sponsors.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['sponsors'] = Sponsor.objects.all() + return context From 62b5327af55ab258b4bc7109eef330a51aa02a15 Mon Sep 17 00:00:00 2001 From: hoangvu5 Date: Mon, 7 Apr 2025 19:13:41 -0400 Subject: [PATCH 7/8] Add Sponsors button to navbar --- src/templates/base.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/templates/base.html b/src/templates/base.html index b4dc5f1..4c38837 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -140,6 +140,9 @@ +