diff --git a/backend/Ugra_hackaton/settings.py b/backend/Ugra_hackaton/settings.py index 6a3ccad..75fd41e 100644 --- a/backend/Ugra_hackaton/settings.py +++ b/backend/Ugra_hackaton/settings.py @@ -39,6 +39,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', + 'django_filters', 'back', ] @@ -55,7 +56,8 @@ MIDDLEWARE = [ REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', - ] + ], + 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] } ROOT_URLCONF = 'Ugra_hackaton.urls' @@ -140,6 +142,9 @@ USE_TZ = True STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'static' +MEDIA_ROOT = BASE_DIR / 'media' +MEDIA_URL = '/media/' + EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.gmail.com' diff --git a/backend/Ugra_hackaton/urls.py b/backend/Ugra_hackaton/urls.py index 2d0ce46..ee21fee 100644 --- a/backend/Ugra_hackaton/urls.py +++ b/backend/Ugra_hackaton/urls.py @@ -1,7 +1,9 @@ from django.contrib import admin from django.urls import path, include +from django.conf.urls.static import static +from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('back.urls')), -] +] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT) \ No newline at end of file diff --git a/backend/back/admin.py b/backend/back/admin.py index 7dadec1..ff9293f 100644 --- a/backend/back/admin.py +++ b/backend/back/admin.py @@ -2,4 +2,6 @@ from django.contrib import admin from . import models admin.site.register(models.Profile) +admin.site.register(models.CheckPoint) +admin.site.register(models.Game) # Register your models here. diff --git a/backend/back/migrations/0002_checkpoint_game.py b/backend/back/migrations/0002_checkpoint_game.py new file mode 100644 index 0000000..5193ea9 --- /dev/null +++ b/backend/back/migrations/0002_checkpoint_game.py @@ -0,0 +1,39 @@ +# Generated by Django 3.1.3 on 2020-11-28 13:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('back', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='CheckPoint', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('check_type', models.CharField(choices=[('QR', 'QR Code'), ('GPS', 'GPS Coordinates')], max_length=20)), + ('name', models.CharField(max_length=150)), + ('coordinates_lat', models.DecimalField(blank=True, decimal_places=6, max_digits=8, null=True)), + ('coordinates_lon', models.DecimalField(blank=True, decimal_places=6, max_digits=8, null=True)), + ('description', models.TextField()), + ('next_checkpoint_id', models.DecimalField(blank=True, decimal_places=0, max_digits=4, null=True)), + ('qr_data', models.TextField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='Game', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100)), + ('description', models.TextField()), + ('average_time', models.DecimalField(decimal_places=0, max_digits=4)), + ('lenght', models.DecimalField(decimal_places=0, max_digits=6)), + ('co_op', models.BooleanField()), + ('max_gamers', models.DecimalField(decimal_places=0, max_digits=3)), + ('active', models.BooleanField(default=True)), + ], + ), + ] diff --git a/backend/back/migrations/0003_auto_20201128_1939.py b/backend/back/migrations/0003_auto_20201128_1939.py new file mode 100644 index 0000000..78088e7 --- /dev/null +++ b/backend/back/migrations/0003_auto_20201128_1939.py @@ -0,0 +1,39 @@ +# Generated by Django 3.1.3 on 2020-11-28 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('back', '0002_checkpoint_game'), + ] + + operations = [ + migrations.AddField( + model_name='checkpoint', + name='address', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AddField( + model_name='checkpoint', + name='last', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='checkpoint', + name='start', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='game', + name='slug', + field=models.SlugField(default='dddd', unique=True), + preserve_default=False, + ), + migrations.AlterField( + model_name='game', + name='title', + field=models.CharField(max_length=100, unique=True), + ), + ] diff --git a/backend/back/models.py b/backend/back/models.py index 4663d91..155799d 100644 --- a/backend/back/models.py +++ b/backend/back/models.py @@ -1,8 +1,13 @@ from django.db import models from django.contrib.auth.models import User -from django.db.models.signals import post_save +from django.db.models.signals import post_save, pre_save from django.dispatch import receiver +CheckPointTypes = [ + ('QR','QR Code'), + ('GPS','GPS Coordinates') +] + class Profile(models.Model): user = models.OneToOneField(User, on_delete = models.CASCADE) points = models.DecimalField(max_digits=7, decimal_places=0, default = 0) @@ -10,7 +15,34 @@ class Profile(models.Model): def __str__(self): return(f'{self.user.username} - {self.user.email}') +class Game(models.Model): + title = models.CharField(max_length = 100, blank = False, null = False, unique = True) + description = models.TextField(blank = False, null = False) + average_time = models.DecimalField(max_digits = 4, decimal_places=0, blank = False, null = False) + lenght = models.DecimalField(max_digits = 6, decimal_places= 0, blank = False, null = False) + co_op = models.BooleanField(blank = False, null = False) + max_gamers = models.DecimalField(max_digits = 3, decimal_places = 0, blank = False, null = False) + active = models.BooleanField(default = True) + slug = models.SlugField(unique = True, blank = True, null = False) + +class CheckPoint(models.Model): + check_type = models.CharField(choices = CheckPointTypes, max_length = 20, blank = False, null = False) + name = models.CharField(max_length = 150, blank = False, null = False) + coordinates_lat = models.DecimalField(max_digits = 8, decimal_places = 6, blank = True, null = True) + coordinates_lon = models.DecimalField(max_digits = 8, decimal_places = 6, blank = True, null = True) + description = models.TextField(blank = False, null = False) + next_checkpoint_id = models.DecimalField(max_digits = 4, decimal_places = 0, blank = True, null = True) + qr_data = models.TextField(blank = True, null = True) + last = models.BooleanField(default = False) + start = models.BooleanField(default = False) + address = models.CharField(max_length = 200, blank = True, null = True) + @receiver(post_save, sender = User) def create_profile(sender, instance, created, **kwargs): if(created): - Profile.objects.create(user = instance) \ No newline at end of file + Profile.objects.create(user = instance) + +@receiver(pre_save, sender = Game) +def add_game_slug(sender, instance, **kwargs): + if(instance.slug == ''): + instance.slug = f"{instance.title.replace(' ','_')}" \ No newline at end of file diff --git a/backend/back/serializers.py b/backend/back/serializers.py index 35f0250..e7faf4e 100644 --- a/backend/back/serializers.py +++ b/backend/back/serializers.py @@ -1,6 +1,11 @@ from rest_framework import serializers from django.contrib.auth.models import User -from . import models +from .models import Game + +class GameListSerializer(serializers.ModelSerializer): + class Meta: + model = Game + fields = '__all__' class UserRegisterSerializer(serializers.ModelSerializer): email = serializers.EmailField(required=True) diff --git a/backend/back/urls.py b/backend/back/urls.py index c99d2eb..5396778 100644 --- a/backend/back/urls.py +++ b/backend/back/urls.py @@ -3,6 +3,9 @@ from rest_framework.authtoken.views import obtain_auth_token from . import views urlpatterns = [ + path('games', views.ListGamesAPIView.as_view(), name = 'ListGames'), + path('game/', views.SingleGameAPIView.as_view(), name = 'SingleGame'), + # path('game//take_part',), path('register', views.UserRegisterAPIView, name = 'UserRegister'), path('login', obtain_auth_token, name = 'UserLogin'), path('logout', views.UserLogoutAPIView, name = 'UserLogout'), diff --git a/backend/back/views.py b/backend/back/views.py index 297fda2..2902372 100644 --- a/backend/back/views.py +++ b/backend/back/views.py @@ -10,9 +10,12 @@ from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.template.loader import render_to_string from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.core.mail import EmailMultiAlternatives -from .serializers import UserRegisterSerializer, UserResetPasswordSerializer, UserPasswordSerializer +from .serializers import UserRegisterSerializer, UserResetPasswordSerializer, UserPasswordSerializer, GameListSerializer from django.utils.html import strip_tags from django.contrib.auth.password_validation import validate_password +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework.filters import OrderingFilter, SearchFilter +from .models import Game import six import threading @@ -23,6 +26,23 @@ class EmailTokenGenerator(PasswordResetTokenGenerator): email_token_gen = EmailTokenGenerator() password_token_gen = PasswordResetTokenGenerator() +class ListGamesAPIView(generics.ListAPIView): + serializer_class = GameListSerializer + permission_classes = [permissions.IsAuthenticated] + filter_backends = [SearchFilter, OrderingFilter, DjangoFilterBackend] + filterset_fields = ['co_op','max_gamers','active','average_time'] + ordering_fields = ['max_gamers','active','average_time','name'] + search_fields = ['name', 'description'] + + def get_queryset(self): + return Game.objects.filter(active = True) + +class SingleGameAPIView(generics.RetrieveAPIView): + serializer_class = GameListSerializer + permission_classes = [permissions.IsAuthenticated] + lookup_field = 'slug' + queryset = Game.objects.all() + @api_view(['POST']) @permission_classes([~permissions.IsAuthenticated]) def UserRegisterAPIView(request):