Skip to content

Commit

Permalink
Add json-ld and simple sub pages for event and bars
Browse files Browse the repository at this point in the history
  • Loading branch information
autoantwort committed Jun 15, 2024
1 parent a61cab4 commit f7c1fe7
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 43 deletions.
82 changes: 82 additions & 0 deletions main/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.utils import formats
from django.utils.text import slugify
from ics import Event as IcsEvent, Organizer, DisplayAlarm, Geo

from studibars.settings import JSON_LD_BASE_URL


class Weekday(models.IntegerChoices):
MONDAY = 1, 'Montag'
Expand All @@ -16,6 +20,17 @@ class Weekday(models.IntegerChoices):
SUNDAY = 7, 'Sonntag'


ENGLISH_WEEKDAYS = {
Weekday.MONDAY: 'Monday',
Weekday.TUESDAY: 'Tuesday',
Weekday.WEDNESDAY: 'Wednesday',
Weekday.THURSDAY: 'Thursday',
Weekday.FRIDAY: 'Friday',
Weekday.SATURDAY: 'Saturday',
Weekday.SUNDAY: 'Sunday',
}


class WeekdayField(models.IntegerField):

def __init__(self, *args, **kwargs):
Expand Down Expand Up @@ -77,6 +92,47 @@ def day_text(self):
return "1., 3. & 5. " + self.get_day_display()
return "Wöchentlich"

def json_ld_postal_address(self) -> dict:
return {
"@type": "PostalAddress",
"streetAddress": self.street,
"addressLocality": self.city,
"addressRegion": "NRW",
"postalCode": self.zip_code,
"addressCountry": "DE",
}

def url_path(self):
return reverse("bar_view", args=[self.id, slugify(self.name)])

def to_json_ld(self) -> dict:
json_ld = {
"@context": "https://schema.org",
"@type": "BarOrPub",
"name": self.name,
"address": self.json_ld_postal_address(),
"priceRange": "$",
"openingHoursSpecification": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ENGLISH_WEEKDAYS[self.day],
"opens": str(self.start_time),
"closes": str(self.end_time) or "02:00",
},
"url": JSON_LD_BASE_URL + self.url_path(),
}
if self.menu_url:
json_ld["menu"] = self.menu_url
json_ld["hasMenu"] = self.menu_url
if self.longitude and self.latitude:
json_ld["geo"] = {
"@type": "GeoCoordinates",
"latitude": float(self.latitude),
"longitude": float(self.longitude),
}
if self.website:
json_ld["sameAs"] = self.website
return json_ld


class Event(models.Model):
name = models.CharField(max_length=254)
Expand Down Expand Up @@ -104,5 +160,31 @@ def to_ics_event(self) -> IcsEvent:
ics_event.alarms.append(alarm)
return ics_event

def url_path(self):
return reverse("event_view", args=[self.id, slugify(f"{self.name}-{self.bar.name}-{self.start_date.date()}")])

def to_json_ld(self) -> dict:
event = {
"@context": "https://schema.org",
"@type": "Event",
"name": self.name,
"description": self.description,
"startDate": str(self.start_date),
"endDate": str(self.end_date or self.start_date + timedelta(hours=5)),
"eventStatus": "https://schema.org/EventScheduled",
"eventAttendanceMode": "https://schema.org/OfflineEventAttendanceMode",
"location": {
"@type": "Place",
"name": self.bar.name,
"address": self.bar.json_ld_postal_address(),
},
"organizer": self.bar.to_json_ld(),
"isAccessibleForFree": True,
"url": JSON_LD_BASE_URL + self.url_path(),
}
if self.poster:
event["image"] = self.poster.url
return event

def __str__(self):
return self.name
5 changes: 5 additions & 0 deletions main/templates/main/bar.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% extends "base.html" %}

{% block content %}
<h1>{{ bar.name }}</h1>
{% endblock %}
10 changes: 10 additions & 0 deletions main/templates/main/event.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% extends "base.html" %}

{% block content %}
<div class="d-flex justify-content-center">

<div style="max-width: 450px" class="col-12">
{% include "./event_card.html" %}
</div>
</div>
{% endblock %}
38 changes: 38 additions & 0 deletions main/templates/main/event_card.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% load imagekit %}
<div class="card">
<div class="card-header d-flex justify-content-between">
<span class="fw-bold">{{ event.bar }}</span>
<span>{{ event.start_date|date:"d.m." }} ab {{ event.start_date|date:"H:i" }}
<a class="align-middle" href="{% url 'download_event_ics' event_id=event.id %}">
<i class="bi bi-calendar-plus align-top"></i>
</a>
</span>
</div>
{% if event.poster %}
{% generateimage 'studibars:poster1x' source=event.poster as img1 %}
{% generateimage 'studibars:poster1_5x' source=event.poster as img1_5 %}
{% generateimage 'studibars:poster2x' source=event.poster as img2 %}
<img alt="Bild {{ event.name }}" src="{{ img1.url }}"
srcset="{{ img1.url }}, {{ img1_5.url }} 1.5x, {{ img2.url }} 2x"
width="{{ img1.width }}" height="{{ img1.height }}"
class="w-100 h-auto" loading="lazy"
>
{% endif %}
{% if event.description or not event.poster %}
<div class="card-body">
<h3 class="card-title">{{ event.name }}</h3>
{% if event.description %}
<p class="card-text">{{ event.description }}</p>
{% endif %}
</div>
{% endif %}
<div class="card-footer">
<small class="text-body-secondary d-flex justify-content-between">
<a target="_blank" class="text-decoration-none"
href="https://maps.google.com/?q={{ event.bar.name }}, {{ event.bar.street }}, {{ event.bar.zip_code }} {{ event.bar.city }}">
{{ event.bar.street }}
</a>
<span>{{ event.start_date|date:"d.m." }} ab {{ event.start_date|date:"H:i" }}</span>
</small>
</div>
</div>
40 changes: 1 addition & 39 deletions main/templates/main/main.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
{% load l10n %}
{% load imagekit %}


{% block content %}
<div class="mb-4" style="position: relative; height: 400px">
<img class="w-100 d-absolute object-fit-cover mb-3" style="position: absolute; opacity: 80%" height="400px"
Expand Down Expand Up @@ -247,44 +246,7 @@ <h5 class="text-nowrap text-black">{{ bar.name }}</h5>
<div class="row" id="events">
{% for event in events %}
<div class="col-sm-6 col-lg-4 mb-4" id="event-{{ event.id }}">
<div class="card">
<div class="card-header d-flex justify-content-between">
<span class="fw-bold">{{ event.bar }}</span>
<span>{{ event.start_date|date:"d.m." }} ab {{ event.start_date|date:"H:i" }}
<a class="align-middle" href="{% url 'download_event_ics' event_id=event.id %}">
<i class="bi bi-calendar-plus align-top"></i>
</a>
</span>
</div>
{% if event.poster %}
{% generateimage 'studibars:poster1x' source=event.poster as img1 %}
{% generateimage 'studibars:poster1_5x' source=event.poster as img1_5 %}
{% generateimage 'studibars:poster2x' source=event.poster as img2 %}
<img alt="Bild {{ event.name }}" src="{{ img1.url }}"
srcset="{{ img1.url }}, {{ img1_5.url }} 1.5x, {{ img2.url }} 2x"
width="{{ img1.width }}" height="{{ img1.height }}"
class="w-100 h-auto" loading="lazy"
>
{% endif %}
{% if event.description or not event.poster %}
<div class="card-body">
<h3 class="card-title">{{ event.name }}</h3>
{% if event.description %}
<p class="card-text">{{ event.description }}</p>
{% endif %}
</div>
{% endif %}
<div class="card-footer">
<small class="text-body-secondary d-flex justify-content-between">
<a target="_blank" class="text-decoration-none"
href="https://maps.google.com/?q={{ event.bar.name }}, {{ event.bar.street }}, {{ event.bar.zip_code }} {{ event.bar.city }}">
{{ event.bar.street }}
</a>
<span>{{ event.start_date|date:"d.m." }} ab {{ event.start_date|date:"H:i" }}</span>
</small>
</div>

</div>
{% include "./event_card.html" %}
</div>
{% endfor %}
</div>
Expand Down
2 changes: 2 additions & 0 deletions main/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
path('main', views.main_view, name='main'),
path('ics/event/<int:event_id>/', views.download_event_ics, name='download_event_ics'),
path('ics/bar/events/<int:bar_id>/', views.download_bar_events_ics, name='download_bar_events_ics'),
path('bar/<int:bar_id>/<name>/', views.bar_view, name='bar_view'),
path('event/<int:event_id>/<name>/', views.event_view, name='event_view'),
]
37 changes: 37 additions & 0 deletions main/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import datetime
import json
from collections import defaultdict
from traceback import _safe_string

from django.http import HttpResponse, Http404
from django.shortcuts import render
from django.utils.safestring import mark_safe
from ics import Calendar
from ics.grammar.parse import ContentLine
from rest_framework import viewsets, permissions
Expand Down Expand Up @@ -58,19 +61,24 @@ class Poster2x(ImageSpec):

# Create your views here.
def main_view(request):
json_ld = []
bars_by_weekday = defaultdict(list)
for bar in Bar.objects.all().order_by('start_time'):
bars_by_weekday[bar.day].append(bar)
json_ld.append(bar.to_json_ld())
bars = []
for day in Weekday.choices[:-3]:
bars.append((day[1], bars_by_weekday[day[0]]))
now = datetime.datetime.now()
events = Event.objects.filter(start_date__gte=datetime.date.today())
for event in events:
json_ld.append(event.to_json_ld())
# Check if it's a weekday (Monday=0, ..., Sunday=6) + if the time is between 6:00 and 19:00
if 0 <= now.weekday() <= 4 and 6 <= now.hour < 19:
events = events.exclude(bar__name__icontains="symposion")
return render(request, 'main/main.html', {
'title': 'Home',
'json_ld': mark_safe(json.dumps(json_ld)),
'weekdays': Weekday.choices[:-3],
'bars_by_day': bars,
'bars': Bar.objects.all().order_by('day', 'start_time'),
Expand All @@ -79,6 +87,35 @@ def main_view(request):
})


def bar_view(request, bar_id, name):
try:
bar = Bar.objects.get(id=bar_id)
except Bar.DoesNotExist:
raise Http404
json_ld = [bar.to_json_ld()]
events = bar.event_set.filter(start_date__gte=datetime.date.today())
for event in events:
json_ld.append(event.to_json_ld())
return render(request, 'main/bar.html', {
'title': bar.name,
'json_ld': mark_safe(json.dumps(json_ld)),
'bar': bar,
'events': events.order_by('start_date'),
})


def event_view(request, event_id, name):
try:
event = Event.objects.get(id=event_id)
except Event.DoesNotExist:
raise Http404
return render(request, 'main/event.html', {
'title': f"{event.bar.name} - {event.name} - {event.start_date.date()}",
'json_ld': mark_safe(json.dumps(event.to_json_ld())),
'event': event,
})


def download_event_ics(request, event_id):
try:
event = Event.objects.get(id=event_id)
Expand Down
2 changes: 2 additions & 0 deletions studibars/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

DNS_POSTFIXES = ["", "-ac", "-aachen"]

JSON_LD_BASE_URL = "https://studibars-ac.de"

ALLOWED_HOSTS = ['127.0.0.1', '0.0.0.0', 'localhost'] + [f"{prefix}studibars{postfix}.de" for prefix in ["", "www."] for postfix in DNS_POSTFIXES]
CSRF_TRUSTED_ORIGINS = [f"https://{prefix}studibars{postfix}.de" for prefix in ["", "www."] for postfix in DNS_POSTFIXES]

Expand Down
13 changes: 9 additions & 4 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
<meta content="Eine Übersichtsseite über die Studi Bars in Aachen. Die Bars in den Wohnheimen werden von Studierenden betrieben und es gibt für wenig Geld Bier und Cocktails."
name="description">
<meta content="Studi Bars, Bar, Aachen, Studenten, Studierende, Bier, Cocktails, Events, günstig" name="keywords">
{% if json_ld %}
<script type="application/ld+json">
{{ json_ld }}
</script>
{% endif %}
</head>

<body>
Expand All @@ -33,16 +38,16 @@
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse justify-content-md-center" id="navbarCollapse">
<a class="navbar-brand d-md-block d-none" href="#">Studibars Aachen</a>
<a class="navbar-brand d-md-block d-none" href="/#">Studibars Aachen</a>
<ul class="navbar-nav mb-2 mb-md-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
<a class="nav-link active" aria-current="page" href="/#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#die-bars">Die Bars</a>
<a class="nav-link" href="/#die-bars">Die Bars</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#events">Events</a>
<a class="nav-link" href="/#events">Events</a>
</li>
<li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
<div class="vr d-none d-lg-flex h-100 mx-lg-2 text-white"></div>
Expand Down

0 comments on commit f7c1fe7

Please sign in to comment.