Skip to content

Commit 5af5e81

Browse files
committed
feat: make navbar button CTA dynamic via admin
1 parent aaa98de commit 5af5e81

File tree

5 files changed

+74
-6
lines changed

5 files changed

+74
-6
lines changed

app/announcements/admin.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.contrib import admin
22

3-
from .models import Announcement, RibbonCTA
3+
from .models import Announcement, ButtonCTA, RibbonCTA
44

55

66
@admin.register(Announcement)
@@ -28,3 +28,16 @@ class RibbonCTAAdmin(admin.ModelAdmin):
2828
("Status", {"fields": ("is_active",)}),
2929
("Metadata", {"fields": ("created_at", "updated_at")}),
3030
)
31+
32+
33+
@admin.register(ButtonCTA)
34+
class ButtonCTAAdmin(admin.ModelAdmin):
35+
list_display = ("label", "url", "is_active", "created_at", "updated_at")
36+
list_filter = ("is_active", "created_at")
37+
search_fields = ("label", "url")
38+
readonly_fields = ("created_at", "updated_at")
39+
fieldsets = (
40+
("Content", {"fields": ("label", "url")}),
41+
("Status", {"fields": ("is_active",)}),
42+
("Metadata", {"fields": ("created_at", "updated_at")}),
43+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Generated by Django 5.2.7 on 2026-03-18 03:07
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('announcements', '0003_ribboncta'),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name='ButtonCTA',
15+
fields=[
16+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17+
('label', models.CharField(max_length=100)),
18+
('url', models.URLField()),
19+
('is_active', models.BooleanField(default=True)),
20+
('created_at', models.DateTimeField(auto_now_add=True)),
21+
('updated_at', models.DateTimeField(auto_now=True)),
22+
],
23+
options={
24+
'verbose_name': 'Button CTA',
25+
'verbose_name_plural': 'Button CTAs',
26+
'ordering': ['-created_at'],
27+
},
28+
),
29+
]

app/announcements/models.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ class Meta:
3535
verbose_name_plural = "Announcements"
3636

3737

38+
class ButtonCTA(models.Model):
39+
label = models.CharField(max_length=100)
40+
url = models.URLField()
41+
is_active = models.BooleanField(default=True)
42+
created_at = models.DateTimeField(auto_now_add=True)
43+
updated_at = models.DateTimeField(auto_now=True)
44+
45+
def __str__(self):
46+
return self.label
47+
48+
@classmethod
49+
def get_active(cls):
50+
"""Get the first active button CTA."""
51+
return cls.objects.filter(is_active=True).first()
52+
53+
class Meta:
54+
ordering = ["-created_at"]
55+
verbose_name = "Button CTA"
56+
verbose_name_plural = "Button CTAs"
57+
58+
3859
class RibbonCTA(models.Model):
3960
message = models.CharField(max_length=255)
4061
cta_text = models.CharField(max_length=100, default="LEARN MORE")

app/home/templates/home/components/navbar.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@
8282
</ul>
8383
</li>
8484
{% endfor %}
85+
{% if button_cta %}
8586
<li class="mt-2">
86-
<a href="https://ti.to/pythonph/pythonasia-2026/" target="_blank" class="btn btn-primary w-full text-center">Get Tickets</a>
87+
<a href="{{ button_cta.url }}" target="_blank" class="btn btn-primary w-full text-center">{{ button_cta.label }}</a>
8788
</li>
89+
{% endif %}
8890
</ul>
8991
</div>
9092
<!-- Header Links -->
@@ -132,11 +134,13 @@
132134
</ul>
133135
</div>
134136
<!-- Ticket Button (desktop only) -->
137+
{% if button_cta %}
135138
<div class="hidden lg:block">
136-
<a href="https://ti.to/pythonph/pythonasia-2026/" target="_blank" class="btn btn-primary btn-wide py-2 px-4 sm:py-3.5 sm:px-8 text-white">
137-
<span class="lg:inline font-bantayog text-base sm:text-xl">Get Tickets</span>
139+
<a href="{{ button_cta.url }}" target="_blank" class="btn btn-primary btn-wide py-2 px-4 sm:py-3.5 sm:px-8 text-white">
140+
<span class="lg:inline font-bantayog text-base sm:text-xl">{{ button_cta.label }}</span>
138141
</a>
139142
</div>
143+
{% endif %}
140144
</div>
141145

142146
</div>

config/context_processors.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
def announcement_context(request):
2-
"""Inject latest published announcement and active ribbon CTA into template context."""
3-
from app.announcements.models import Announcement, RibbonCTA
2+
"""Inject latest published announcement and active navbar CTAs into template context."""
3+
from app.announcements.models import Announcement, ButtonCTA, RibbonCTA
44

55
return {
66
"latest_announcement": Announcement.get_latest_published(),
77
"ribbon_cta": RibbonCTA.get_active(),
8+
"button_cta": ButtonCTA.get_active(),
89
}

0 commit comments

Comments
 (0)