API for Calendars

This commit is contained in:
2026-01-12 22:48:08 -05:00
parent f6672a880a
commit aacc0af901
9 changed files with 137 additions and 25 deletions

View File

@@ -3,12 +3,12 @@ from .models import *
class CalendarAdmin(admin.ModelAdmin): class CalendarAdmin(admin.ModelAdmin):
# prepopulated_fields = {"slug": ("shortname",)} # prepopulated_fields = {"slug": ("shortname",)}
list_display = ("name", "shortcode") list_display = ("name", "shortcode", "published")
class ScraperAdmin(admin.ModelAdmin): class ScraperAdmin(admin.ModelAdmin):
# prepopulated_fields = {"slug": ("shortname",)} # prepopulated_fields = {"slug": ("shortname",)}
list_display = ("name", "items", "new_items", "last_ran") list_display = ("name", "items", "new_items", "last_ran", "calendar")
class OrganizationAdmin(admin.ModelAdmin): class OrganizationAdmin(admin.ModelAdmin):
# prepopulated_fields = {"slug": ("shortname",)} # prepopulated_fields = {"slug": ("shortname",)}

View File

@@ -1,5 +1,5 @@
import os, sys import os, sys
from datetime import datetime from datetime import datetime, timedelta
from dateutil import relativedelta from dateutil import relativedelta
from time import sleep from time import sleep
import pytz import pytz
@@ -19,7 +19,7 @@ odt_next_month = datetime.now() + plus_one_month
# Get Scraper name, item count and online_calendar (virtcal) # Get Scraper name, item count and online_calendar (virtcal)
def getScraper(venue, webite, cal): def getScraper(venue, website, cal):
virtcal = Calendar.objects.get(shortcode='000') virtcal = Calendar.objects.get(shortcode='000')
try: try:
scraper, created = Scraper.objects.get_or_create( scraper, created = Scraper.objects.get_or_create(
@@ -183,7 +183,7 @@ def createBasicEvent(event, event_type, venue):
venue = venue venue = venue
) )
new_event = add_calendars(new_event, event) new_event = add_calendars(new_event, event)
print("\n+new event+\n") # print("\n+new event+")
return new_event, created return new_event, created
# Create iCal Event # Create iCal Event
@@ -198,7 +198,7 @@ def createBasiciCalEvent(event, event_type, venue):
venue = venue venue = venue
) )
new_event = add_calendars(new_event, event) new_event = add_calendars(new_event, event)
print("\n+new event+\n") print("Success")
return new_event, created return new_event, created
# Create Detailed Event with Details & Guests # Create Detailed Event with Details & Guests
@@ -216,7 +216,7 @@ def createDetailedEvent(event, event_type, venue, scraper):
venue = venue venue = venue
) )
new_event = add_calendars(new_event, event) new_event = add_calendars(new_event, event)
print("\n+new event+\n") print("Success")
return new_event, created return new_event, created
# Create iCal event from DF_Online & Medellin # Create iCal event from DF_Online & Medellin
@@ -260,7 +260,7 @@ def getiCalEvents(gcal, scraper, venue, event_type):
return events return events
# Build iCal Events and Send to Create # Build iCal Events and Send to Create
def buildiCalEvents(events, event_type, scraper): def buildiCalEvents(events, event_type, scraper, venue):
for event in events: for event in events:
e = {} e = {}
e['calendars'] = event['calendars'] e['calendars'] = event['calendars']
@@ -322,7 +322,7 @@ def getiCalRepeateEvents(gcal, scraper, venue, event_type, cal):
try: try:
if rules['FREQ'][0] == 'WEEKLY': if rules['FREQ'][0] == 'WEEKLY':
if datetime.today().weekday() != 0: if datetime.today().weekday() != 0:
event = digitools.splitLocation(event, "Medellin") event = splitLocation(event, city="Medellin")
date = datetime.today().date() - timedelta(days=datetime.today().weekday()) date = datetime.today().date() - timedelta(days=datetime.today().weekday())
date = datetime.combine(date, event['dateStart'].time()) date = datetime.combine(date, event['dateStart'].time())
days = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"] days = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"]
@@ -333,27 +333,28 @@ def getiCalRepeateEvents(gcal, scraper, venue, event_type, cal):
iCalEventRepeatFilter(day, date, event, scraper, event['venue'], "Ed") iCalEventRepeatFilter(day, date, event, scraper, event['venue'], "Ed")
except Exception as e: except Exception as e:
print("Error: ", e, "\n\n\n\n") print("Error: ", event, e, "\n\n\n\n")
pass pass
def iCalEventRepeatFilterteEvent(day, date, event, scraper, venue, event_type): def iCalEventRepeatFilter(day, date, event, scraper, venue, event_type):
days = [day-1, day+6, day+13] days = [day-1, day+6, day+13]
for day in days: for day in days:
event['dateStamp'] = date + timedelta(days=day) event['dateStamp'] = date + timedelta(days=day)
event['dateStart'] = event['dateStamp'] event['dateStart'] = event['dateStamp']
digitools.createCleanIcalEvent(event, scraper, venue, event_type) createCleanIcalEvent(event, scraper, venue, event_type)
return return
def splitLocation(event, **kwargs): def splitLocation(event, **kwargs):
loc_split = event['strLocation'].split(',') loc_split = event['strLocation'].split(',')
ppr(loc_split)
venue_name = loc_split[0] venue_name = loc_split[0]
venue, created = Organization.objects.get_or_create( venue, created = Organization.objects.get_or_create(
name=venue_name, name=venue_name,
) )
event['venue'] = venue event['venue'] = venue
if city: # if kwargs['city']:
venue.city = kwargs['city'] # venue.city = kwargs['city']
venue.save() # venue.save()
return event return event
# ARCHIVED Methods # ARCHIVED Methods

View File

@@ -0,0 +1,44 @@
# Generated by Django 5.1.1 on 2026-01-12 23:30
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('events', '0038_remove_event_calendar_event_calendar'),
]
operations = [
migrations.AlterModelOptions(
name='calendar',
options={'ordering': ['name'], 'verbose_name_plural': 'Calendars'},
),
migrations.AddField(
model_name='calendar',
name='published',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='organization',
name='cal',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='events.calendar'),
preserve_default=False,
),
migrations.AlterField(
model_name='organization',
name='membership',
field=models.CharField(choices=[('Nm', 'Non-Member'), ('Ds', 'DigiSnaxx'), ('Dsp', 'DigiSnaxx +')], default='0', max_length=31),
),
migrations.AlterField(
model_name='organization',
name='org_type',
field=models.CharField(choices=[('Fb', 'Food & Beverage'), ('Re', 'Retail'), ('Se', 'Service'), ('Vn', 'Venue'), ('Ud', 'Undefined')], default='3', max_length=31),
),
migrations.AlterField(
model_name='promo',
name='promo_type',
field=models.CharField(choices=[('Ar', 'Art'), ('Fo', 'Food'), ('Ev', 'Event'), ('Re', 'Retail'), ('Sv', 'Service'), ('Ma', 'Mutual Aid'), ('Ca', 'Classified'), ('Jo', 'Job Opening'), ('Ja', 'Journal Article'), ('Sp', 'Startup Pitch'), ('An', 'Academia Nut'), ('Su', 'Survey Question')], default='0', max_length=15),
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.1.1 on 2026-01-12 23:49
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('events', '0039_alter_calendar_options_calendar_published_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='calendar',
options={'ordering': ['-published', 'id'], 'verbose_name_plural': 'Calendars'},
),
migrations.AlterField(
model_name='organization',
name='cal',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cal_events', to='events.calendar'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.1 on 2026-01-13 00:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('events', '0040_alter_calendar_options_alter_organization_cal'),
]
operations = [
migrations.AlterField(
model_name='event',
name='calendar',
field=models.ManyToManyField(blank=True, null=True, related_name='events', to='events.calendar'),
),
]

View File

@@ -9,10 +9,12 @@ class Calendar(models.Model):
name = models.CharField(max_length=31, unique=True) name = models.CharField(max_length=31, unique=True)
shortcode = models.CharField(max_length=3, unique=True) shortcode = models.CharField(max_length=3, unique=True)
desc = models.TextField(blank=True, null=True) desc = models.TextField(blank=True, null=True)
published = models.BooleanField(default=False)
class Meta: class Meta:
verbose_name_plural = "Calendars" verbose_name_plural = "Calendars"
ordering = ['name',] ordering = ['-published', 'id',]
def __unicode__(self): def __unicode__(self):
return "%s" % self.shortcode return "%s" % self.shortcode
@@ -29,6 +31,7 @@ class Scraper(models.Model):
new_items = models.IntegerField(blank=True, null=True) new_items = models.IntegerField(blank=True, null=True)
last_ran = models.DateTimeField(blank=True, null=True) last_ran = models.DateTimeField(blank=True, null=True)
class Meta: class Meta:
verbose_name_plural = "Scrapers" verbose_name_plural = "Scrapers"
ordering = ['name',] ordering = ['name',]
@@ -78,7 +81,7 @@ class Organization(models.Model):
address_type = models.CharField(max_length=31, blank=True, null=True) address_type = models.CharField(max_length=31, blank=True, null=True)
address_complete = models.CharField(max_length=63, blank=True, null=True) address_complete = models.CharField(max_length=63, blank=True, null=True)
cal = models.ForeignKey(Calendar, on_delete=models.CASCADE, related_name="cal_events")
barrio = models.CharField(max_length=127, blank=True, null=True) barrio = models.CharField(max_length=127, blank=True, null=True)
city = models.CharField(max_length=31, blank=True, null=True) city = models.CharField(max_length=31, blank=True, null=True)
state = models.CharField(max_length=15, blank=True, null=True) state = models.CharField(max_length=15, blank=True, null=True)
@@ -113,15 +116,15 @@ class Organization(models.Model):
class Event(models.Model): class Event(models.Model):
EVENT_TYPE = ( EVENT_TYPE = (
('Ot', 'Other'), ('Ot', '🤔'),
('Mu', 'Music'), ('Mu', '🎶'),
('Va', 'Visual Art'), ('Va', 'Visual Art'),
('Gv', 'Government'), ('Gv', '🛠️'),
('Ce', 'Civic Engagement'), ('Ce', 'Civic Engagement'),
('Ed', 'Educational'), ('Ed', '🍎'),
('Ma', 'Mutual Aid'), ('Ma', 'Mutual Aid'),
('Th', 'Theater'), ('Th', '🎭'),
('Co', 'Comedy'), ('Co', '🍿'),
) )
EVENT_STATE = ( EVENT_STATE = (
('live', 'Live & Direct'), ('live', 'Live & Direct'),
@@ -134,7 +137,7 @@ class Event(models.Model):
show_date = models.DateTimeField() show_date = models.DateTimeField()
show_day = models.DateField() show_day = models.DateField()
calendar = models.ManyToManyField(Calendar, blank=True, null=True) calendar = models.ManyToManyField(Calendar, blank=True, null=True, related_name="events")
scraper = models.ForeignKey(Scraper, on_delete=models.CASCADE, null=True) scraper = models.ForeignKey(Scraper, on_delete=models.CASCADE, null=True)
venue = models.ForeignKey(Organization, on_delete=models.CASCADE) venue = models.ForeignKey(Organization, on_delete=models.CASCADE)

View File

@@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Event, Organization, Promo from .models import Calendar, Event, Organization, Promo
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -35,6 +35,7 @@ class ScopesPermission(BasePermission):
## Events ## ## Events ##
############ ############
class OrganizationSerializer(serializers.ModelSerializer): class OrganizationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Organization model = Organization
@@ -52,6 +53,18 @@ class EventSerializer(serializers.ModelSerializer):
depth = 2 depth = 2
# fields = ('id', 'name',) # fields = ('id', 'name',)
class CalSerializer(serializers.ModelSerializer):
events_count = serializers.SerializerMethodField()
class Meta:
model = Calendar
fields = ['id', 'name', 'shortcode', 'events_count', 'published']
# fields = '__all__'
def get_events_count(self, obj):
# obj is the current Tag instance
return obj.events.count()
class PromoSerializer(serializers.ModelSerializer): class PromoSerializer(serializers.ModelSerializer):
organization = OrganizationSerializer(many=False) organization = OrganizationSerializer(many=False)
# event_type = serializers.CharField(source='get_event_type_display') # event_type = serializers.CharField(source='get_event_type_display')

View File

@@ -20,6 +20,7 @@ from .views import *
urlpatterns = [ urlpatterns = [
re_path(r'^events/', EventsAPIView.as_view(), name="get-events"), re_path(r'^events/', EventsAPIView.as_view(), name="get-events"),
re_path(r'^promo/', PromoAPIView.as_view(), name="get-promo"), re_path(r'^promo/', PromoAPIView.as_view(), name="get-promo"),
re_path(r'^cals/', CalAPIView.as_view(), name="get-cals"),
# re_path(r'^events-token/', EventsTokenAPIView.as_view(), name="get-token-events"), # re_path(r'^events-token/', EventsTokenAPIView.as_view(), name="get-token-events"),
] ]

View File

@@ -6,6 +6,7 @@ from .models import *
from .serializers import * from .serializers import *
from django.db.models import Q from django.db.models import Q
from django.db.models import Count
from rest_framework import generics from rest_framework import generics
from rest_framework.decorators import authentication_classes, permission_classes from rest_framework.decorators import authentication_classes, permission_classes
@@ -26,6 +27,14 @@ td = timedelta(hours=7)
odt = datetime.now() - td odt = datetime.now() - td
# Create your views here. # Create your views here.
class CalAPIView(generics.ListAPIView):
serializer_class = CalSerializer
queryset = Calendar.objects.all()
# queryset = Calendar.objects.filter(published=True)
permission_classes = [HasAPIKey]
class EventsAPIView(generics.ListAPIView): class EventsAPIView(generics.ListAPIView):
serializer_class = EventSerializer serializer_class = EventSerializer
queryset = Event.objects.filter(show_date__gte=odt).order_by('show_date') queryset = Event.objects.filter(show_date__gte=odt).order_by('show_date')