Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add eventpost functionality #231

Merged
merged 5 commits into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ RUN pip install -r requirements.txt
ADD . /
WORKDIR /

CMD python manage.py makemigrations authentication && python manage.py makemigrations eventposts && python manage.py migrate && python manage.py runserver 0.0.0.0:9000
## POSTGRES WAIT SCRIPT FROM https://github.com/ufoscout/docker-compose-wait
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.9.0/wait /wait
RUN chmod +x /wait
CMD /wait && python manage.py makemigrations authentication && python manage.py makemigrations eventposts && python manage.py migrate && python manage.py test eventposts && python manage.py runserver 0.0.0.0:9000

EXPOSE 9000
4 changes: 4 additions & 0 deletions backend/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@

'PORT': '5432',

'TEST': {
'NAME': 'mytestdatabase'
}

}
}

Expand Down
5 changes: 3 additions & 2 deletions backend/eventposts/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.db import models
from authentication.models import User
from django.contrib.postgres.fields import ArrayField
from datetime import datetime

def empty_list():
return list([])
Expand All @@ -12,15 +13,15 @@ class Post(models.Model):
content = models.TextField(default="")
title = models.TextField(default="")

creation_date = models.DateTimeField(auto_now_add=True)
creation_date = models.DateTimeField(default=datetime.now())
location = models.TextField(default="")

class Meta:
abstract = True


class EventPost(Post):
date = models.DateTimeField(auto_now_add=True)
date = models.DateTimeField(default=datetime.now())
duration = models.IntegerField(default=60)

sport = models.CharField(max_length=30)
Expand Down
2 changes: 1 addition & 1 deletion backend/eventposts/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import EventPost, Post
from eventposts.models import EventPost, Post

class EventSerializer(serializers.ModelSerializer):
class Meta:
Expand Down
168 changes: 167 additions & 1 deletion backend/eventposts/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,169 @@
from django.test import TestCase
from rest_framework.test import force_authenticate
from rest_framework.test import APITestCase, APIRequestFactory
from rest_framework import status
from eventposts.models import EventPost
from authentication.models import User
from eventposts.serializers import EventSerializer
from django.urls import reverse
from django.db.models import Q
from datetime import datetime, timedelta


class EventPostTests(APITestCase):
def setUp(self):
# create user and get auth token
self.user = User.objects.create_user(email="user@user.com", password="1234567", username="user")
resp = self.client.post(reverse('token_create'), {'username': 'user', 'password': '1234567'})
self.token = resp.data['access']

# create additional users for spectators and players
self.user2 = User.objects.create_user(email="user2@user.com", password="1234567", username="user2")
self.user3 = User.objects.create_user(email="user3@user.com", password="1234567", username="user3")

# create mock events for testing
self.event_01 = EventPost.objects.create(owner=self.user, title='Football Event',
content='We are organizing a football match with FC Barcelona fans.',
location='Madrid', date=datetime(2021, 9, 3), sport='Football',
min_age=13, max_age=45, player_capacity=14, spec_capacity=20,
min_skill_level=3, max_skill_level=4, latitude=40.43103333341609,
longitude=-3.705507357022727, duration=90, players=[self.user.id],
spectators=[self.user2.id, self.user3.id])

self.event_02 = EventPost.objects.create(owner=self.user, title='basketball event',
content='We are organizing a basketball match with Anadolu Efes fans.',
location='levent', date=datetime(2022, 5, 5), sport='Basketball',
min_age=20, max_age=33, player_capacity=6, spec_capacity=10,
min_skill_level=0, max_skill_level=5, latitude=41.08204996728227,
longitude=29.016445404346598, duration=120,
spectators=[self.user.id, self.user2.id, self.user3.id])

self.event_03 = EventPost.objects.create(owner=self.user, title="Let's show some NBA skillz",
content='Guys, today we are gathering to play basketball, join us!',
location='Washington', date=datetime(2022, 4, 4), sport='Basketball',
min_age=18, max_age=30, player_capacity=8, spec_capacity=10,
min_skill_level=3, max_skill_level=5, latitude=38.90785448747658,
longitude=-77.04329853399994, duration=120)

self.event_04 = EventPost.objects.create(owner=self.user, title="Tek kale aylık",
content='hep maç olmaz bu sefer tek kale aylık ayarlıyoruz,'
' katılım sınırlıdır',
location='etiler', date=datetime(2021, 1, 13), sport='Football',
min_age=13, max_age=17, player_capacity=5, spec_capacity=18,
min_skill_level=3, max_skill_level=4, latitude=41.13274943188016,
longitude=29.105688623416825, duration=60,
players=[self.user.id, self.user2.id], spectators=[self.user3.id])

self.basketball_games = EventSerializer(EventPost.objects.filter(sport="Basketball"), many=True).data

self.football_games = EventSerializer(EventPost.objects.filter(sport="Football"), many=True).data

self.player_capacity_between_6_10_games = EventSerializer(
EventPost.objects.filter(Q(player_capacity=6) | Q(player_capacity=8)), many=True).data

self.spec_capacity_between_15_25_games = self.football_games

self.age_between_18_35_games = self.basketball_games

self.in_turkey_games = EventSerializer(EventPost.objects.filter(
Q(location="levent") | Q(location="etiler")), many=True).data

self.date_inside_2022_games = self.basketball_games

self.duration_between_45_100_games = self.football_games
self.games_created_by_user = EventSerializer(EventPost.objects.all(), many=True).data
self.creation_date_today = EventSerializer(EventPost.objects.all(), many=True).data
self.num_players_between_1_5_games = self.football_games
self.num_spectators_between_3_5_games = EventSerializer(EventPost.objects.filter(title="basketball event"),
many=True).data

self.skill_between_2_4 = self.football_games

def test_filter_by_query(self):
response = self.client.get(reverse('eventpost-list'), {'query': 'basketball'}, HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.basketball_games)

def test_filter_by_date(self):
response = self.client.get(reverse('eventpost-list'), {'min_date': datetime(2021, 12, 12),
'max_date': datetime(2023, 1, 1)},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.date_inside_2022_games)

def test_filter_by_creation_date(self):
response = self.client.get(reverse('eventpost-list'), {'min_creation_date': (datetime.today() - timedelta(3)),
'max_creation_date': (datetime.today() + timedelta(1))},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.creation_date_today)

def test_filter_by_player_capacity(self):
response = self.client.get(reverse('eventpost-list'), {'min_player_capacity': 6, 'max_player_capacity': 10},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.player_capacity_between_6_10_games)

def test_filter_by_spec_capacity(self):
response = self.client.get(reverse('eventpost-list'), {'min_spectator_capacity': 15, 'max_spectator_capacity': 25},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.spec_capacity_between_15_25_games)

def test_filter_by_location(self):
response = self.client.get(reverse('eventpost-list'), {'location': 'le'},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.in_turkey_games)

def test_filter_by_duration(self):
response = self.client.get(reverse('eventpost-list'), {'min_duration': 45, 'max_duration': 100},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.duration_between_45_100_games)

def test_filter_by_sport(self):
response = self.client.get(reverse('eventpost-list'), {'sport': 'Basketball'},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.basketball_games)

def test_filter_by_owner(self):
response = self.client.get(reverse('eventpost-list'), {'owner_id': self.user.id},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.games_created_by_user)

def test_filter_by_age(self):
response = self.client.get(reverse('eventpost-list'), {'min_age': 18, 'max_age': 35},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.age_between_18_35_games)

def test_filter_by_coordinates(self):
response = self.client.get(reverse('eventpost-list'), {'min_latitude': 36.23763062438484,
'max_latitude': 42.01901802424485,
'min_longitude': 26.732105369671633,
'max_longitude': 44.3513027746188},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.in_turkey_games)

def test_filter_by_player_numbers(self):
response = self.client.get(reverse('eventpost-list'), {'min_players': 1, 'max_players': 5},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.num_players_between_1_5_games)

def test_filter_by_spectator_numbers(self):
response = self.client.get(reverse('eventpost-list'), {'min_spectators': 3, 'max_spectators': 5},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.num_spectators_between_3_5_games)

def test_filter_by_skill(self):
response = self.client.get(reverse('eventpost-list'), {'min_skill_level': 2, 'max_skill_level': 4},
HTTP_AUTHORIZATION=f'JWT {self.token}')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['results'], self.skill_between_2_4)

# Create your tests here.
139 changes: 137 additions & 2 deletions backend/eventposts/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from .models import EventPost, Post
from .serializers import EventSerializer
from eventposts.models import EventPost, Post
from authentication.models import User
from eventposts.serializers import EventSerializer
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.http import JsonResponse
from rest_framework import status
from rest_framework.response import Response
from rest_framework import viewsets
from rest_framework.pagination import PageNumberPagination
from django.db.models import Q, F, Func, IntegerField


class EventPostsPagination(PageNumberPagination):
Expand Down Expand Up @@ -50,6 +52,139 @@ def authenticate(self):
user, _ = self.JWTauth.authenticate(self.request)
return user.id == self.request.data["owner"]

def get_queryset(self):
queryset = EventPost.objects.all()

# get all parameters for search
query = self.request.query_params.get('query')

min_player_capacity = self.request.query_params.get('min_player_capacity')
max_player_capacity = self.request.query_params.get('max_player_capacity')

min_spec_capacity = self.request.query_params.get('min_spectator_capacity')
max_spec_capacity = self.request.query_params.get('max_spectator_capacity')

min_players = self.request.query_params.get('min_players')
max_players = self.request.query_params.get('max_players')

min_specs = self.request.query_params.get('min_spectators')
max_specs = self.request.query_params.get('max_spectators')

location = self.request.query_params.get('location')

min_date = self.request.query_params.get('min_date')
max_date = self.request.query_params.get('max_date')

min_duration = self.request.query_params.get('min_duration')
max_duration = self.request.query_params.get('max_duration')

sport = self.request.query_params.get('sport')

owner_id = self.request.query_params.get('owner')

min_age = self.request.query_params.get('min_age')
max_age = self.request.query_params.get('max_age')

min_latitude = self.request.query_params.get('min_latitude')
max_latitude = self.request.query_params.get('max_latitude')
min_longitude = self.request.query_params.get('min_longitude')
max_longitude = self.request.query_params.get('max_longitude')

min_skill = self.request.query_params.get('min_skill_level')
max_skill = self.request.query_params.get('max_skill_level')

min_creation_date = self.request.query_params.get('min_creation_date')
max_creation_date = self.request.query_params.get('max_creation_date')

# filter by query by searching in both title and description
if query is not None:
queryset = queryset.filter(Q(title__icontains=query) | Q(content__icontains=query))

# filter by player capacity
if min_player_capacity is not None:
queryset = queryset.filter(player_capacity__gte=min_player_capacity)
if max_player_capacity is not None:
queryset = queryset.filter(player_capacity__lte=max_player_capacity)

# filter by number of players registered to event
if min_players is not None:
queryset = queryset.annotate(player_len=Func(F('players'),
1, function='array_length',
output_field=IntegerField())).filter(
player_len__gte=min_players)

if max_players is not None:
queryset = queryset.annotate(player_len=Func(F('players'),
1, function='array_length',
output_field=IntegerField())).filter(
player_len__lte=max_players)

# filter by spectator capacity
if min_spec_capacity is not None:
queryset = queryset.filter(spec_capacity__gte=min_spec_capacity)
if max_spec_capacity is not None:
queryset = queryset.filter(spec_capacity__lte=max_spec_capacity)

# filter by number of spectators registered to event
if min_specs is not None:
queryset = queryset.annotate(spec_len=Func(F('spectators'),
1, function='array_length',
output_field=IntegerField())).filter(
spec_len__gte=min_specs)
if max_specs is not None:
queryset = queryset.annotate(spec_len=Func(F('spectators'), 1, function='array_length',
output_field=IntegerField())).filter(spec_len__lte=max_specs)

# filter by name of the location
if location is not None:
queryset = queryset.filter(Q(location__icontains=location))

# filter by event date
if min_date is not None:
queryset = queryset.filter(date__gte=min_date)
if max_date is not None:
queryset = queryset.filter(date__lte=max_date)

# filter by duration of the event
if min_duration is not None:
queryset = queryset.filter(duration__gte=min_duration)
if max_duration is not None:
queryset = queryset.filter(duration__lte=max_duration)

# filter by sport category
if sport is not None:
queryset = queryset.filter(sport=sport)

# filter by owner of the event
if owner_id is not None:
queryset = queryset.filter(owner=User.objects.get(id=owner_id))

# filter by age interval
if min_age is not None:
queryset = queryset.filter(min_age__gte=min_age)
if max_age is not None:
queryset = queryset.filter(max_age__lte=max_age)

# filter by coordinates whether the locations are inside the rectangle
if min_latitude is not None and max_latitude is not None:
queryset = queryset.filter(Q(latitude__lte=max_latitude) & Q(latitude__gte=min_latitude))
if min_longitude is not None and max_longitude is not None:
queryset = queryset.filter(Q(longitude__lte=max_longitude) & Q(longitude__gte=min_longitude))

# filter by skill levels
if min_skill is not None:
queryset = queryset.filter(min_skill_level__gte=min_skill)
if max_skill is not None:
queryset = queryset.filter(max_skill_level__lte=max_skill)

# filter by creation date
if min_creation_date is not None:
queryset = queryset.filter(creation_date__gte=min_creation_date)
if max_creation_date is not None:
queryset = queryset.filter(creation_date__lte=max_creation_date)

return queryset

def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
Expand Down