From 8ece3aaa1fdda616e245ec162761dc1a7ea848c9 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Sun, 5 Jan 2025 14:49:15 +0300 Subject: [PATCH 1/7] feat(sponsor): add sponsor model and tests --- core/settings_base.py | 1 + sponsors/__init__.py | 0 sponsors/admin.py | 17 ++++++ sponsors/apps.py | 6 +++ sponsors/migrations/0001_initial.py | 54 +++++++++++++++++++ sponsors/migrations/__init__.py | 0 sponsors/models.py | 80 +++++++++++++++++++++++++++++ sponsors/tests/__init__.py | 0 sponsors/tests/test_models.py | 55 ++++++++++++++++++++ sponsors/views.py | 3 ++ 10 files changed, 216 insertions(+) create mode 100644 sponsors/__init__.py create mode 100644 sponsors/admin.py create mode 100644 sponsors/apps.py create mode 100644 sponsors/migrations/0001_initial.py create mode 100644 sponsors/migrations/__init__.py create mode 100644 sponsors/models.py create mode 100644 sponsors/tests/__init__.py create mode 100644 sponsors/tests/test_models.py create mode 100644 sponsors/views.py diff --git a/core/settings_base.py b/core/settings_base.py index 916c8ef..c0bf4d0 100644 --- a/core/settings_base.py +++ b/core/settings_base.py @@ -37,6 +37,7 @@ "custom_auth", "allauth", "allauth.account", + "sponsors", ] MIDDLEWARE = [ diff --git a/sponsors/__init__.py b/sponsors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sponsors/admin.py b/sponsors/admin.py new file mode 100644 index 0000000..b7149d0 --- /dev/null +++ b/sponsors/admin.py @@ -0,0 +1,17 @@ +from django.contrib import admin + +from sponsors.models import Sponsor, SponsorshipPackage, SponsorshipFile + + +@admin.register(Sponsor) +class SponsorAdmin(admin.ModelAdmin): + pass + +@admin.register(SponsorshipPackage) +class SponsorshipPackageAdmin(admin.ModelAdmin): + pass + +@admin.register(SponsorshipFile) +class SponsorshipFileAdmin(admin.ModelAdmin): + pass + diff --git a/sponsors/apps.py b/sponsors/apps.py new file mode 100644 index 0000000..c0183c4 --- /dev/null +++ b/sponsors/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class SponsorsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'sponsors' diff --git a/sponsors/migrations/0001_initial.py b/sponsors/migrations/0001_initial.py new file mode 100644 index 0000000..a2ac1ca --- /dev/null +++ b/sponsors/migrations/0001_initial.py @@ -0,0 +1,54 @@ +# Generated by Django 4.2.16 on 2025-01-05 10:44 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='SponsorshipFile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True, help_text='A Description of the file.')), + ('item', models.FileField(upload_to='sponsors_files')), + ], + ), + migrations.CreateModel( + name='SponsorshipPackage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.IntegerField(default=1)), + ('name', models.CharField(help_text='The name of the sponsorship package.', max_length=255)), + ('number_available', models.IntegerField(null=True, validators=[django.core.validators.MinValueValidator(0)])), + ('currency', models.CharField(default='$', help_text='Currency symbol of the sponsorship package.', max_length=20)), + ('amount', models.DecimalField(decimal_places=2, help_text='The amount of the sponsorship package.', max_digits=12)), + ('short_description', models.TextField(help_text='A short description of the sponsorship package.')), + ('files', models.ManyToManyField(blank=True, help_text='The files of the sponsorship package.', related_name='packages', to='sponsors.sponsorshipfile')), + ], + options={ + 'ordering': ['order', '-amount', 'name'], + }, + ), + migrations.CreateModel( + name='Sponsor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order', models.IntegerField(default=1)), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(help_text='A description of the sponsor.')), + ('url', models.URLField(blank=True, default='', help_text='The URL of the sponsor if needed.')), + ('packages', models.ManyToManyField(related_name='sponsors', to='sponsors.sponsorshippackage')), + ], + options={ + 'ordering': ['order', 'name', 'id'], + }, + ), + ] diff --git a/sponsors/migrations/__init__.py b/sponsors/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sponsors/models.py b/sponsors/models.py new file mode 100644 index 0000000..8eb4fbc --- /dev/null +++ b/sponsors/models.py @@ -0,0 +1,80 @@ +from django.db import models +from django.core.validators import MinValueValidator +from django.utils.translation import gettext_lazy as _ + + +class SponsorshipFile(models.Model): + """File for use in sponsor and sponsorship package description.""" + name = models.CharField(max_length=255) + description = models.TextField( + blank=True, + help_text=_("A Description of the file.") + ) + item = models.FileField( + upload_to='sponsors_files' + ) + + def __str__(self): + return u"%s (%s)" % (self.name, self.item.url) + + +class SponsorshipPackage(models.Model): + """A description of a sponsorship package.""" + order = models.IntegerField(default=1) + name = models.CharField( + max_length=255, + help_text=_("The name of the sponsorship package.") + ) + number_available = models.IntegerField( + null=True, + validators=[MinValueValidator(0)] + ) + currency = models.CharField( + max_length=20, + default="$", + help_text=_("Currency symbol of the sponsorship package.") + ) + amount = models.DecimalField( + max_digits=12, + decimal_places=2, + help_text=_("The amount of the sponsorship package.") + ) + short_description = models.TextField( + help_text=_("A short description of the sponsorship package.") + ) + files = models.ManyToManyField( + SponsorshipFile, + related_name="packages", + blank=True, + help_text=_("The files of the sponsorship package.") + ) + + class Meta: + ordering = ["order", "-amount", "name"] + + def __str__(self): + return u"%s (amount: %.0f)" % (self.name, self.amount) + + +class Sponsor(models.Model): + """A conference sponsor.""" + order = models.IntegerField(default=1) + name = models.CharField(max_length=255) + packages = models.ManyToManyField( + SponsorshipPackage, + related_name="sponsors", + ) + # TODO: check markitup package + description = models.TextField( + help_text=_("A description of the sponsor.") + ) + url = models.URLField( + default="", + blank=True, + help_text=_("The URL of the sponsor if needed.") + ) + + class Meta: + ordering = ["order", "name", "id"] + + diff --git a/sponsors/tests/__init__.py b/sponsors/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sponsors/tests/test_models.py b/sponsors/tests/test_models.py new file mode 100644 index 0000000..6faec2d --- /dev/null +++ b/sponsors/tests/test_models.py @@ -0,0 +1,55 @@ +import pytest + +from typing import List, Tuple +from sponsors.models import Sponsor, SponsorshipPackage + + +def create_package(name: str, amount: float) -> SponsorshipPackage: + """Create a sponsor""" + package = SponsorshipPackage.objects.create( + name=name, + amount=amount + ) + return package + + +def create_sponsor(name: str, packages: List[Tuple[str, float]]) -> Sponsor: + """Create a sponsor with the given name and packages.""" + sponsor = Sponsor.objects.create(name=name) + for name, amount in packages: + package = create_package(name, amount) + sponsor.packages.add(package) + sponsor.save() + return sponsor + + + +class TestSponsorshipModels: + + @pytest.mark.django_db + def test_sponsorship_package_creation(self): + package = create_package(u"Gold", 1000) + + assert package is not None + assert package.name == u"Gold" + assert package.amount == 1000 + + @pytest.mark.django_db + def test_sponsorship_with_single_package(self): + """Create sponsor with multiple sponsorship packages.""" + sponsor = create_sponsor(u"Django", [ + (u"Gold", 1000) + ]) + + assert sponsor is not None + assert sponsor.name == u"Django" + assert sponsor.packages.count() == 1 + + package = sponsor.packages.first() + + assert package is not None + assert package.name == u"Gold" + assert package.amount == 1000 + + + diff --git a/sponsors/views.py b/sponsors/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/sponsors/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From 5b0d080e9a7a981ecace6892b2fb2c807375e9b3 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Mon, 13 Jan 2025 15:34:07 +0300 Subject: [PATCH 2/7] feat(sponsor): add sponsor model and tests - added custom template tag based wafer - tests for the models - added view - Sample sponsors template - added models to admin --- sponsors/admin.py | 9 ++- ..._rename_sponsorshipfile_file_taggedfile.py | 27 +++++++ sponsors/models.py | 30 +++++++- sponsors/templates/sponsors/sponsors.html | 40 ++++++++++ sponsors/templatetags/__init__.py | 0 sponsors/templatetags/sponsors.py | 27 +++++++ sponsors/tests/test_models.py | 73 ++++++++++++++++++- sponsors/urls.py | 8 ++ sponsors/views.py | 10 ++- 9 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 sponsors/migrations/0002_rename_sponsorshipfile_file_taggedfile.py create mode 100644 sponsors/templates/sponsors/sponsors.html create mode 100644 sponsors/templatetags/__init__.py create mode 100644 sponsors/templatetags/sponsors.py create mode 100644 sponsors/urls.py diff --git a/sponsors/admin.py b/sponsors/admin.py index b7149d0..76bae0b 100644 --- a/sponsors/admin.py +++ b/sponsors/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from sponsors.models import Sponsor, SponsorshipPackage, SponsorshipFile +from sponsors.models import Sponsor, SponsorshipPackage, File, TaggedFile @admin.register(Sponsor) @@ -11,7 +11,10 @@ class SponsorAdmin(admin.ModelAdmin): class SponsorshipPackageAdmin(admin.ModelAdmin): pass -@admin.register(SponsorshipFile) -class SponsorshipFileAdmin(admin.ModelAdmin): +@admin.register(File) +class FileAdmin(admin.ModelAdmin): pass +@admin.register(TaggedFile) +class TaggedFileAdmin(admin.ModelAdmin): + pass \ No newline at end of file diff --git a/sponsors/migrations/0002_rename_sponsorshipfile_file_taggedfile.py b/sponsors/migrations/0002_rename_sponsorshipfile_file_taggedfile.py new file mode 100644 index 0000000..2cc6b93 --- /dev/null +++ b/sponsors/migrations/0002_rename_sponsorshipfile_file_taggedfile.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.16 on 2025-01-12 12:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0001_initial'), + ] + + operations = [ + migrations.RenameModel( + old_name='SponsorshipFile', + new_name='File', + ), + migrations.CreateModel( + name='TaggedFile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('tag_name', models.CharField(help_text='The name of the tag.', max_length=255)), + ('sponsor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to='sponsors.sponsor')), + ('tagged_file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sponsors.file')), + ], + ), + ] diff --git a/sponsors/models.py b/sponsors/models.py index 8eb4fbc..1526f61 100644 --- a/sponsors/models.py +++ b/sponsors/models.py @@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _ -class SponsorshipFile(models.Model): +class File(models.Model): """File for use in sponsor and sponsorship package description.""" name = models.CharField(max_length=255) description = models.TextField( @@ -43,7 +43,7 @@ class SponsorshipPackage(models.Model): help_text=_("A short description of the sponsorship package.") ) files = models.ManyToManyField( - SponsorshipFile, + File, related_name="packages", blank=True, help_text=_("The files of the sponsorship package.") @@ -53,7 +53,7 @@ class Meta: ordering = ["order", "-amount", "name"] def __str__(self): - return u"%s (amount: %.0f)" % (self.name, self.amount) + return u"%s (amount: %.0f)" % (self.name, self.amount,) class Sponsor(models.Model): @@ -64,7 +64,6 @@ class Sponsor(models.Model): SponsorshipPackage, related_name="sponsors", ) - # TODO: check markitup package description = models.TextField( help_text=_("A description of the sponsor.") ) @@ -74,7 +73,30 @@ class Sponsor(models.Model): help_text=_("The URL of the sponsor if needed.") ) + def __str__(self): + return u"%s" % (self.name,) + class Meta: ordering = ["order", "name", "id"] +class TaggedFile(models.Model): + """Tags for files associated with a given sponsor""" + tag_name = models.CharField( + max_length=255, + null=False, + help_text=_("The name of the tag.") + ) + tagged_file = models.ForeignKey( + File, + on_delete=models.CASCADE + ) + sponsor = models.ForeignKey( + Sponsor, + related_name="files", + on_delete=models.CASCADE + ) + + def __str__(self): + return u"%s - (%s)" % (self.sponsor.name, self.tag_name,) + diff --git a/sponsors/templates/sponsors/sponsors.html b/sponsors/templates/sponsors/sponsors.html new file mode 100644 index 0000000..af5b34e --- /dev/null +++ b/sponsors/templates/sponsors/sponsors.html @@ -0,0 +1,40 @@ +{% load sponsors %} +{% sponsors as all_sponsors %} +{% packages as all_packages %} + +

Here are the list of sponsors!

+ + + +

Here are the list of packages!

+ \ No newline at end of file diff --git a/sponsors/templatetags/__init__.py b/sponsors/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sponsors/templatetags/sponsors.py b/sponsors/templatetags/sponsors.py new file mode 100644 index 0000000..38af259 --- /dev/null +++ b/sponsors/templatetags/sponsors.py @@ -0,0 +1,27 @@ +from django import template + +from sponsors.models import Sponsor, SponsorshipPackage + +register = template.Library() + + + +@register.simple_tag +def sponsors(): + return { + "sponsors": Sponsor.objects.all().order_by('packages', 'order', 'id'), + } + + +@register.simple_tag +def packages(): + return { + "packages": SponsorshipPackage.objects.all().prefetch_related("files"), + } + +@register.simple_tag +def sponsor_tagged_image(sponsor, tag): + """return the corresponding url from the tagged image list.""" + if sponsor.files.filter(tag_name=tag).exists(): + return sponsor.files.filter(tag_name=tag).first().tagged_file.item.url + return '' diff --git a/sponsors/tests/test_models.py b/sponsors/tests/test_models.py index 6faec2d..f0dca28 100644 --- a/sponsors/tests/test_models.py +++ b/sponsors/tests/test_models.py @@ -1,8 +1,10 @@ import pytest +import tempfile from typing import List, Tuple -from sponsors.models import Sponsor, SponsorshipPackage +from sponsors.models import Sponsor, SponsorshipPackage, File, TaggedFile +from django.core.files.uploadedfile import SimpleUploadedFile def create_package(name: str, amount: float) -> SponsorshipPackage: """Create a sponsor""" @@ -23,11 +25,27 @@ def create_sponsor(name: str, packages: List[Tuple[str, float]]) -> Sponsor: return sponsor +def create_file(name: str, desc: str) -> File: + """Create a File with a temporary image file.""" + temp_image = tempfile.NamedTemporaryFile(suffix=".png") + test_image = SimpleUploadedFile( + name="test_image.png", + content=open(temp_image.name, "rb").read(), + content_type="image/png" + ) + + return File.objects.create( + name=name, + description=desc, + item=test_image + ) + class TestSponsorshipModels: @pytest.mark.django_db def test_sponsorship_package_creation(self): + """Create a sponsorship package.""" package = create_package(u"Gold", 1000) assert package is not None @@ -36,7 +54,7 @@ def test_sponsorship_package_creation(self): @pytest.mark.django_db def test_sponsorship_with_single_package(self): - """Create sponsor with multiple sponsorship packages.""" + """Create sponsor with single sponsorship packages.""" sponsor = create_sponsor(u"Django", [ (u"Gold", 1000) ]) @@ -51,5 +69,56 @@ def test_sponsorship_with_single_package(self): assert package.name == u"Gold" assert package.amount == 1000 + @pytest.mark.django_db + def test_sponsorship_with_multiple_packages(self): + """Creat sponsor with multiple sponsorship packages.""" + sponsor = create_sponsor(u"Django Org.", [ + (u"Gold", 1000), + (u"Sliver", 500), + ]) + + assert sponsor is not None + assert sponsor.name == u"Django Org." + assert sponsor.packages.count() == 2 + + packages = sponsor.packages.all() + + assert packages is not None + assert packages.count() == 2 + + +class TestFilesModels: + + @pytest.mark.django_db + def test_file_creation(self): + """Creates a file with name and description.""" + file = create_file(name="Awesome image", desc="This is a test file.") + + assert file is not None + assert file.name == u"Awesome image" + assert file.description == u"This is a test file." + assert file.item + + @pytest.mark.django_db + def test_tagged_file_creation(self): + """Create tagged file""" + file = create_file(name="Tagged Image", desc="This is a test file.") + sponsor = create_sponsor(u"Awesome Sponsor", [ + (u"Gold", 1000) + ]) + + assert file is not None + assert sponsor is not None + + tagged_file = TaggedFile.objects.create( + tag_name="logo", + tagged_file=file, + sponsor=sponsor + ) + + assert tagged_file is not None + assert tagged_file.tag_name == u"logo" + assert tagged_file.sponsor == sponsor + diff --git a/sponsors/urls.py b/sponsors/urls.py new file mode 100644 index 0000000..354e722 --- /dev/null +++ b/sponsors/urls.py @@ -0,0 +1,8 @@ +from django.urls import re_path + +from sponsors.views import SponsorsDetailView + +urlpatterns = [ + re_path(r"^$", SponsorsDetailView.as_view(), name="sponsors"), +] + diff --git a/sponsors/views.py b/sponsors/views.py index 91ea44a..5d14b9f 100644 --- a/sponsors/views.py +++ b/sponsors/views.py @@ -1,3 +1,9 @@ -from django.shortcuts import render +from django.views.generic import TemplateView +from sponsors.models import Sponsor + + + +class SponsorsDetailView(TemplateView): + template_name = "sponsors/sponsors.html" + model = Sponsor -# Create your views here. From 802d184c5171e16de10d50fa8d35d9212f908b14 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Mon, 13 Jan 2025 15:35:55 +0300 Subject: [PATCH 3/7] refactor(settings_base): storage config, media config and removed duplicates - Added default storage config - Added media config - Removed duplicate config --- core/settings_base.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/settings_base.py b/core/settings_base.py index c0bf4d0..cd9dc92 100644 --- a/core/settings_base.py +++ b/core/settings_base.py @@ -76,7 +76,9 @@ STORAGES = { - # ... + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage" + }, "staticfiles": { "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", }, @@ -101,6 +103,12 @@ }, ] +# MEDIA +# ------------------------------------------------------------------------------ +# https://docs.djangoproject.com/en/dev/ref/settings/#media-root +MEDIA_ROOT = BASE_DIR / "media" +# https://docs.djangoproject.com/en/dev/ref/settings/#media-url +MEDIA_URL = "/media/" # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ @@ -167,19 +175,16 @@ "signup": "custom_auth.forms.CustomSignupForm", } -SITE_ID = 1 # new ACCOUNT_EMAIL_VERIFICATION = True ACCOUNT_EMAIL_REQUIRED = True ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1 -ACCOUNT_EMAIL_REQUIRED = True ACCOUNT_USER_MODEL_USERNAME_FIELD = None -ACCOUNT_EMAIL_REQUIRED = True ACCOUNT_USERNAME_REQUIRED = False ACCOUNT_AUTHENTICATION_METHOD = "email" ACCOUNT_UNIQUE_EMAIL = True ACCOUNT_LOGOUT_REDIRECT_URL = "/accounts/login/" LOGIN_REDIRECT_URL = "/" -ACCOUNT_LOGIN_ON_PASSWORD_RESET = True # logged automatiquely when success +ACCOUNT_LOGIN_ON_PASSWORD_RESET = True # logged automatically when success ACCOUNT_LOGOUT_ON_GET = True From b60a5ad766a27c3549e92fa387f314c68f501de3 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Mon, 13 Jan 2025 15:36:05 +0300 Subject: [PATCH 4/7] feat(sponsor): add sponsor model and tests - added custom template tag based wafer - tests for the models - added view - Sample sponsors template - added models to admin --- core/urls.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/urls.py b/core/urls.py index 577cbf2..8b14195 100644 --- a/core/urls.py +++ b/core/urls.py @@ -13,9 +13,10 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ - +from django.conf import settings from django.conf.urls.i18n import i18n_patterns from django.contrib import admin +from django.conf.urls.static import static from django.urls import path, include @@ -23,14 +24,19 @@ path("", include("website.urls")), path("accounts/", include("allauth.urls")), path("proposals/", include("proposals.urls")), + path("sponsors/", include("sponsors.urls")), path("admin/", admin.site.urls), path("__reload__/", include("django_browser_reload.urls")), path('i18n/', include('django.conf.urls.i18n')), ] +# Media and static files +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + urlpatterns += i18n_patterns( path("", include("website.urls")), path("accounts/", include("allauth.urls")), path("proposals/", include("proposals.urls")), + path("sponsors/", include("sponsors.urls")), path("admin/", admin.site.urls), ) \ No newline at end of file From 8c9cbb71250b7ed4a4a16090d2a3b154af8e5f50 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Fri, 17 Jan 2025 18:10:43 +0300 Subject: [PATCH 5/7] refactor(models): add hiring field on sponsors model --- sponsors/models.py | 4 ++++ sponsors/templates/sponsors/sponsors.html | 1 + sponsors/tests/test_models.py | 7 ++++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/sponsors/models.py b/sponsors/models.py index 1526f61..714f33e 100644 --- a/sponsors/models.py +++ b/sponsors/models.py @@ -72,6 +72,10 @@ class Sponsor(models.Model): blank=True, help_text=_("The URL of the sponsor if needed.") ) + hiring = models.BooleanField( + default=False, + help_text=_("Whether the sponsor is hiring or not.") + ) def __str__(self): return u"%s" % (self.name,) diff --git a/sponsors/templates/sponsors/sponsors.html b/sponsors/templates/sponsors/sponsors.html index af5b34e..b2d9515 100644 --- a/sponsors/templates/sponsors/sponsors.html +++ b/sponsors/templates/sponsors/sponsors.html @@ -8,6 +8,7 @@

Here are the list of sponsors!

  • Name: {{ sponsor.name }}
  • Description: {{ sponsor.description }}
  • Url: {{ sponsor.url }}
  • +
  • Hiring: {{ sponsor.hiring }}
    • {% for package in sponsor.packages.all %}
    • {{ package.name }} ({{ package.currency }}{{ package.amount }})
    • diff --git a/sponsors/tests/test_models.py b/sponsors/tests/test_models.py index f0dca28..707f753 100644 --- a/sponsors/tests/test_models.py +++ b/sponsors/tests/test_models.py @@ -15,9 +15,9 @@ def create_package(name: str, amount: float) -> SponsorshipPackage: return package -def create_sponsor(name: str, packages: List[Tuple[str, float]]) -> Sponsor: +def create_sponsor(name: str, packages: List[Tuple[str, float]], hiring: bool = False) -> Sponsor: """Create a sponsor with the given name and packages.""" - sponsor = Sponsor.objects.create(name=name) + sponsor = Sponsor.objects.create(name=name, hiring=hiring) for name, amount in packages: package = create_package(name, amount) sponsor.packages.add(package) @@ -57,11 +57,12 @@ def test_sponsorship_with_single_package(self): """Create sponsor with single sponsorship packages.""" sponsor = create_sponsor(u"Django", [ (u"Gold", 1000) - ]) + ], hiring=True) assert sponsor is not None assert sponsor.name == u"Django" assert sponsor.packages.count() == 1 + assert sponsor.hiring package = sponsor.packages.first() From 421bc6fa618ee2ada89a595b4b97e7476d15a3a6 Mon Sep 17 00:00:00 2001 From: theShinigami Date: Tue, 21 Jan 2025 11:40:19 +0300 Subject: [PATCH 6/7] refactor(models): add custom symbol added in Sponsorship package. --- sponsors/migrations/0003_sponsor_hiring.py | 18 ++++++++++++++++++ .../0004_sponsorshippackage_symbol.py | 18 ++++++++++++++++++ .../0005_alter_sponsorshippackage_symbol.py | 18 ++++++++++++++++++ sponsors/models.py | 5 +++++ sponsors/templates/sponsors/sponsors.html | 2 +- 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 sponsors/migrations/0003_sponsor_hiring.py create mode 100644 sponsors/migrations/0004_sponsorshippackage_symbol.py create mode 100644 sponsors/migrations/0005_alter_sponsorshippackage_symbol.py diff --git a/sponsors/migrations/0003_sponsor_hiring.py b/sponsors/migrations/0003_sponsor_hiring.py new file mode 100644 index 0000000..b1d4e17 --- /dev/null +++ b/sponsors/migrations/0003_sponsor_hiring.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.16 on 2025-01-17 15:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0002_rename_sponsorshipfile_file_taggedfile'), + ] + + operations = [ + migrations.AddField( + model_name='sponsor', + name='hiring', + field=models.BooleanField(default=False, help_text='Whether the sponsor is hiring or not.'), + ), + ] diff --git a/sponsors/migrations/0004_sponsorshippackage_symbol.py b/sponsors/migrations/0004_sponsorshippackage_symbol.py new file mode 100644 index 0000000..d939b9d --- /dev/null +++ b/sponsors/migrations/0004_sponsorshippackage_symbol.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.16 on 2025-01-21 08:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0003_sponsor_hiring'), + ] + + operations = [ + migrations.AddField( + model_name='sponsorshippackage', + name='symbol', + field=models.CharField(blank=True, help_text='The symbol of the sponsorship package.', max_length=1), + ), + ] diff --git a/sponsors/migrations/0005_alter_sponsorshippackage_symbol.py b/sponsors/migrations/0005_alter_sponsorshippackage_symbol.py new file mode 100644 index 0000000..1acfc22 --- /dev/null +++ b/sponsors/migrations/0005_alter_sponsorshippackage_symbol.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.16 on 2025-01-21 08:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sponsors', '0004_sponsorshippackage_symbol'), + ] + + operations = [ + migrations.AlterField( + model_name='sponsorshippackage', + name='symbol', + field=models.CharField(blank=True, help_text='The symbol of the sponsorship package.', max_length=100), + ), + ] diff --git a/sponsors/models.py b/sponsors/models.py index 714f33e..92b08ce 100644 --- a/sponsors/models.py +++ b/sponsors/models.py @@ -48,6 +48,11 @@ class SponsorshipPackage(models.Model): blank=True, help_text=_("The files of the sponsorship package.") ) + symbol = models.CharField( + max_length=100, + blank=True, + help_text=_("The symbol of the sponsorship package.") + ) class Meta: ordering = ["order", "-amount", "name"] diff --git a/sponsors/templates/sponsors/sponsors.html b/sponsors/templates/sponsors/sponsors.html index b2d9515..e2e10f0 100644 --- a/sponsors/templates/sponsors/sponsors.html +++ b/sponsors/templates/sponsors/sponsors.html @@ -11,7 +11,7 @@

      Here are the list of sponsors!

    • Hiring: {{ sponsor.hiring }}
      • {% for package in sponsor.packages.all %} -
      • {{ package.name }} ({{ package.currency }}{{ package.amount }})
      • +
      • {{ package.symbol }}{{ package.name }} ({{ package.currency }}{{ package.amount }})
      • {% endfor %}
      {% sponsor_tagged_image sponsor "main_logo" as logo_url %} From bc099815067a0e124337fa850339d2940581064f Mon Sep 17 00:00:00 2001 From: theShinigami Date: Tue, 21 Jan 2025 16:42:38 +0300 Subject: [PATCH 7/7] refactor(models): add hiring url to sponsors model --- sponsors/models.py | 5 +++++ sponsors/templates/sponsors/sponsors.html | 1 + sponsors/tests/test_models.py | 7 ++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sponsors/models.py b/sponsors/models.py index 92b08ce..4e81611 100644 --- a/sponsors/models.py +++ b/sponsors/models.py @@ -81,6 +81,11 @@ class Sponsor(models.Model): default=False, help_text=_("Whether the sponsor is hiring or not.") ) + hiring_url = models.URLField( + default="", + blank=True, + help_text=_("Hiring URL of the sponsor.") + ) def __str__(self): return u"%s" % (self.name,) diff --git a/sponsors/templates/sponsors/sponsors.html b/sponsors/templates/sponsors/sponsors.html index e2e10f0..dbdfec0 100644 --- a/sponsors/templates/sponsors/sponsors.html +++ b/sponsors/templates/sponsors/sponsors.html @@ -9,6 +9,7 @@

      Here are the list of sponsors!

    • Description: {{ sponsor.description }}
    • Url: {{ sponsor.url }}
    • Hiring: {{ sponsor.hiring }}
    • +
    • Hiring URL: {{ sponsor.hiring_url }}
      • {% for package in sponsor.packages.all %}
      • {{ package.symbol }}{{ package.name }} ({{ package.currency }}{{ package.amount }})
      • diff --git a/sponsors/tests/test_models.py b/sponsors/tests/test_models.py index 707f753..3300a6c 100644 --- a/sponsors/tests/test_models.py +++ b/sponsors/tests/test_models.py @@ -15,9 +15,9 @@ def create_package(name: str, amount: float) -> SponsorshipPackage: return package -def create_sponsor(name: str, packages: List[Tuple[str, float]], hiring: bool = False) -> Sponsor: +def create_sponsor(name: str, packages: List[Tuple[str, float]], hiring: bool = False, hiring_url: str = "") -> Sponsor: """Create a sponsor with the given name and packages.""" - sponsor = Sponsor.objects.create(name=name, hiring=hiring) + sponsor = Sponsor.objects.create(name=name, hiring=hiring, hiring_url=hiring_url) for name, amount in packages: package = create_package(name, amount) sponsor.packages.add(package) @@ -57,12 +57,13 @@ def test_sponsorship_with_single_package(self): """Create sponsor with single sponsorship packages.""" sponsor = create_sponsor(u"Django", [ (u"Gold", 1000) - ], hiring=True) + ], hiring=True, hiring_url="https://example.com") assert sponsor is not None assert sponsor.name == u"Django" assert sponsor.packages.count() == 1 assert sponsor.hiring + assert sponsor.hiring_url == "https://example.com" package = sponsor.packages.first()