diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 6ef1d727fd..30fab561e2 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -365,6 +365,26 @@ class Event(EventMixin, LoggedModel): providers[pp.identifier] = pp return providers + @property + def event_microdata(self): + import json + + eventdict = {"@context": "http://schema.org", "@type": "Event"} + eventdict["location"] = {"@type": "Place", + "address": str(self.location)} + if self.settings.show_times: + eventdict["startDate"] = self.date_from.isoformat() + if self.settings.show_date_to and self.date_to is not None: + eventdict["endDate"] = self.date_to.isoformat() + else: + eventdict["startDate"] = self.date_from.date().isoformat() + if self.settings.show_date_to and self.date_to is not None: + eventdict["endDate"] = self.date_to.date().isoformat() + + eventdict["name"] = str(self.name) + + return json.dumps(eventdict) + def get_invoice_renderers(self) -> dict: """ Returns a dictionary of initialized invoice renderers mapped by their identifiers. diff --git a/src/pretix/presale/templates/pretixpresale/base.html b/src/pretix/presale/templates/pretixpresale/base.html index 669ee7aed1..094bec1f95 100644 --- a/src/pretix/presale/templates/pretixpresale/base.html +++ b/src/pretix/presale/templates/pretixpresale/base.html @@ -30,6 +30,13 @@ {% endcompress %} + {% if event %} + {% autoescape off %} + + {% endautoescape %} + {% endif %} {{ html_head|safe }} diff --git a/src/tests/presale/test_event.py b/src/tests/presale/test_event.py index 6f6cd2fece..5f5463cfd6 100644 --- a/src/tests/presale/test_event.py +++ b/src/tests/presale/test_event.py @@ -1,6 +1,7 @@ import datetime import re from decimal import Decimal +from json import loads from django.conf import settings from django.core import mail @@ -939,6 +940,49 @@ class EventIcalDownloadTest(EventTestMixin, SoupTest): self.assertIn('LOCATION:Heeeeeere', ical, 'incorrect location') +class EventMicrodataTest(EventTestMixin, SoupTest): + def setUp(self): + super().setUp() + self.event.settings.show_date_to = True + self.event.settings.show_times = True + self.event.location = 'DUMMY ARENA' + self.event.date_from = datetime.datetime(2013, 12, 26, 21, 57, 58, tzinfo=datetime.timezone.utc) + self.event.date_to = self.event.date_from + datetime.timedelta(days=2) + self.event.settings.timezone = 'UTC' + self.event.save() + + def _get_json(self): + doc = self.get_doc('/%s/%s/' % (self.orga.slug, self.event.slug)) + microdata = loads(doc.find(type="application/ld+json").string) + return microdata + + def test_name(self): + md = self._get_json() + self.assertEqual(self.event.name, md['name'], msg='Name not present') + + def test_location(self): + md = self._get_json() + self.assertEqual(self.event.location, md['location']['address'], msg='Location not present') + + def test_date_to(self): + md = self._get_json() + self.assertEqual(self.event.date_to.isoformat(), md['endDate'], msg='Date To not present') + self.event.settings.show_date_to = False + md = self._get_json() + self.assertNotIn(self.event.date_to.isoformat(), md, + msg='Date To present when show date to setting is false') + + def test_no_times(self): + self.event.settings.show_times = False + md = self._get_json() + self.assertNotEqual(self.event.date_from.isoformat(), md['startDate'], msg='Date including time present') + self.assertEqual(self.event.date_from.date().isoformat(), md['startDate'], msg='Date not present at all') + + def test_date_from(self): + md = self._get_json() + self.assertEqual(self.event.date_from.isoformat(), md['startDate'], msg='Date From not present') + + class EventSlugBlacklistValidatorTest(EventTestMixin, SoupTest): def test_slug_validation(self): event = Event(