localist/api/views/event.py

186 lines
6.7 KiB
Python

import json
from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
from django.db import transaction
from django.shortcuts import get_object_or_404
from api.serializers.event import EventSerializer
from api.views.base import BaseView
from web.models.category import Category
from web.models.event_category import EventCategory
from web.models.event import Event
from web.models.tag import Tag
from web.models.event_tag import EventTag
class EventView(BaseView):
SERIALIZER = EventSerializer
def get(self, request, event_id=None):
if event_id:
event = get_object_or_404(Event, pk=event_id, active=True)
return self._build_response(event)
else:
return self._get_events_by_radius(request)
def _get_events_by_radius(self, request):
lat = request.GET.get('lat')
lng = request.GET.get('lng')
r = request.GET.get('r')
if all([lat, lng, r]):
try:
user_location = Point(float(lng), float(lat), srid=4326)
events = Event.objects.filter(active=True).filter(coordinates__dwithin=(user_location, D(mi=float(r)))).all()
return self._build_multi_response(events)
except ValueError:
return self.error_response(400, 'Invalid coordinates or radius format')
else:
return self.error_response(400, 'Must include lat, lng, and r in query string')
@transaction.atomic
def post(self, request):
data = json.loads(request.body)
location = data.get('location', {})
coordinates = Point(location.get("lng"), location.get("lat"), srid=4326)
event = Event(
name=data.get('name'),
description=data.get('description'),
url=data.get('url'),
address=data.get('address'),
status=data.get('status'),
price=data.get('price'),
require_rsvp=data.get('require_rsvp'),
start_time=data.get('start_time'),
end_time=data.get('end_time'),
rain_date=data.get('rain_date'),
email=data.get('email'),
phone_number=data.get('phone_number'),
coordinates=coordinates,
)
event.save()
categories = data.get('categories', [])
self._create_event_categories(categories, event)
tag_names = data.get('tags', [])
self._create_event_tags(tag_names, event)
return self._build_response(event)
def _create_event_categories(self, categories, event):
event_categories = []
for category_id in categories:
category = get_object_or_404(Category, pk=category_id)
event_category = EventCategory(
event=event,
category=category
)
event_categories.append(event_category)
EventCategory.objects.bulk_create(event_categories)
def _create_event_tags(self, tag_names, event):
event_tags = []
for tag_name in tag_names:
tag, created = Tag.objects.get_or_create(name=tag_name)
event_tag = EventTag(
tag=tag,
event=event
)
event_tags.append(event_tag)
EventTag.objects.bulk_create(event_tags)
@transaction.atomic
def put(self, request, event_id):
data = json.loads(request.body)
event = get_object_or_404(Event, pk=event_id)
location = data.get('location', {})
if location:
coordinates = Point(location.get("lng"), location.get("lat"), srid=4326)
event.coordinates = coordinates
event.name = data.get('name', event.name)
event.description = data.get('description', event.description)
event.url = data.get('url', event.url)
event.address = data.get('address', event.address)
event.status = data.get('status', event.status)
event.price = data.get('price', event.price)
event.require_rsvp = data.get('require_rsvp', event.require_rsvp)
event.start_time = data.get('start_time', event.start_time)
event.end_time = data.get('end_time', event.end_time)
event.rain_date = data.get('rain_date', event.rain_date)
event.email = data.get('email', event.email)
event.phone_number = data.get('phone_number', event.phone_number)
categories = data.get('categories', [])
self._update_event_categories(categories, event)
tag_names = data.get('tags', [])
self._update_event_tags(tag_names, event)
event.save()
self._build_response(event)
def _update_event_categories(self, categories, event):
if categories:
current_event_categories = EventCategory.objects.filter(event=event).filter(active=True).all()
current_event_category_map = {ec.category.id: ec for ec in current_event_categories}
for current_event_category in current_event_categories:
if current_event_category.category.id not in categories:
current_event_category.active = False
current_event_category.save()
new_event_categories = []
for category_id in categories:
category = get_object_or_404(Category, pk=category_id)
if category not in current_event_category_map:
event_category = EventCategory(
category=category,
event=event
)
new_event_categories.append(event_category)
if new_event_categories:
EventCategory.objects.bulk_create(new_event_categories)
def _update_event_tags(self, tag_names, event):
if tag_names:
current_event_tags = EventTag.objects.filter(event=event).filter(active=True).all()
current_event_tag_names = [x.name for x in current_event_tags]
for current_event_tag in current_event_tags:
if current_event_tag.tag.name not in tag_names:
current_event_tag.active = False
current_event_tag.save()
new_event_tags = []
for tag_name in tag_names:
if tag_name not in current_event_tag_names:
tag, created = Tag.objects.get_or_create(name=tag_name)
event_tag = EventTag(
tag=tag,
event=event
)
new_event_tags.append(event_tag)
if new_event_tags:
EventTag.objects.bulk_create(new_event_tags)
def delete(self, request, event_id):
event = get_object_or_404(Event, pk=event_id)
event.active = False
event.save()
return self._build_response(event)