Merge branch 'backend' into 'master'

Backend

See merge request dm1sh/hackathon2020_komap!8
This commit is contained in:
Dmitriy Shishkov 2020-11-29 06:46:00 +05:00
commit 94406bfcfb
13 changed files with 141 additions and 33 deletions

3
.gitignore vendored
View File

@ -33,4 +33,5 @@ yarn-error.log*
# vercel
.vercel
.vscode/
.vscode/
.env

1
backend/.gitignore vendored
View File

@ -27,6 +27,7 @@ share/python-wheels/
*.egg
MANIFEST
env/
media/
static/
# PyInstaller

15
backend/Dockerfile Normal file
View File

@ -0,0 +1,15 @@
# pull official base image
FROM python:3
# set work directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt
RUN apt update && apt install netcat -y
# copy project
COPY . .
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

View File

@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
"""
from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@ -20,13 +21,11 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'cn0m$w9+&hn7eus%m2z3m-=9!fz+!*#y_c7lb(4nax^51gfajz'
SECRET_KEY = os.environ.get("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
DEBUG = int(os.environ.get("DEBUG", default=0))
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS").split(" ")
# Application definition
@ -80,23 +79,12 @@ TEMPLATES = [
WSGI_APPLICATION = 'Ugra_hackaton.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': BASE_DIR / 'db.sqlite3',
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'ugra_hackaton',
'USER': 'postgres',
'PASSWORD': 'zo.h0906023',
'NAME': os.environ.get("POSTGRES_DB"),
'USER': os.environ.get("POSTGRES_USER"),
'PASSWORD': os.environ.get("POSTGRES_PASSWORD"),
'HOST': '127.0.0.1',
'PORT': '5432',
}
@ -145,12 +133,12 @@ STATIC_ROOT = BASE_DIR / 'static'
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'
MAX_CHECK_RADIUS = 1
MAX_CHECK_RADIUS = 0.001
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'artemss20030906@gmail.com'
EMAIL_HOST_PASSWORD = 'hbqgvdsqhvkuijuc'
EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD")
EMAIL_PORT = 587
EMAIL_USE_TLS = True

View File

@ -0,0 +1,26 @@
# Generated by Django 3.1.3 on 2020-11-29 05:53
import back.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('back', '0011_game_points'),
]
operations = [
migrations.AddField(
model_name='checkpoint',
name='image',
field=models.ImageField(default='mt.img', upload_to=back.models.get_check_path),
preserve_default=False,
),
migrations.AddField(
model_name='game',
name='image',
field=models.ImageField(default='media/img.png', upload_to=back.models.get_game_path),
preserve_default=False,
),
]

View File

@ -8,6 +8,12 @@ CheckPointTypes = [
('GPS','GPS Coordinates')
]
def get_check_path(instance, filename):
return(f'{instance.game.title}/{instance.name}_{filename}')
def get_game_path(instance, filename):
return(f'{instance.title}/{instance.title}_{filename}')
class Profile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
points = models.DecimalField(max_digits=7, decimal_places=0, default = 0)
@ -25,6 +31,7 @@ class Game(models.Model):
active = models.BooleanField(default = True)
points = models.DecimalField(max_digits = 3, decimal_places = 0, blank = False, null = False)
slug = models.SlugField(unique = True, blank = True, null = False)
image = models.ImageField(upload_to = get_game_path, blank = False, null = False)
class CheckPoint(models.Model):
check_type = models.CharField(choices = CheckPointTypes, max_length = 20, blank = False, null = False)
@ -34,6 +41,7 @@ class CheckPoint(models.Model):
description = models.TextField(blank = False, null = False)
next_checkpoint = models.ForeignKey('self', on_delete = models.CASCADE, blank = True, null = True)
qr_data = models.TextField(blank = True, null = True)
image = models.ImageField(upload_to = get_check_path, blank = False, null = False)
last = models.BooleanField(default = False)
start = models.BooleanField(default = False)
address = models.CharField(max_length = 200, blank = True, null = True)

View File

@ -1,6 +1,6 @@
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Game, Team, Gamer, CheckPoint
from .models import Game, Team, Gamer, CheckPoint, Profile
class GameListSerializer(serializers.ModelSerializer):
class Meta:
@ -17,6 +17,17 @@ class UserRegisterSerializer(serializers.ModelSerializer):
'email'
]
class ProfileInfoSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
class Meta:
model = Profile
fields = [
'points',
'username'
]
def get_username(self, obj):
return obj.user.username
class CheckPointCoordinatesSerializer(serializers.ModelSerializer):
class Meta:
model = CheckPoint
@ -35,11 +46,8 @@ class CurrentCheckPointSerializer(serializers.ModelSerializer):
'name',
'description',
'address',
'image'
]
# def get_done_check_points(self, obj):
# return(CheckPointCoordinatesSerializer(obj).data)
class TeamSerializer(serializers.ModelSerializer):
game = serializers.SerializerMethodField()

View File

@ -12,6 +12,7 @@ urlpatterns = [
path('register', views.UserRegisterAPIView, name = 'UserRegister'),
path('login', obtain_auth_token, name = 'UserLogin'),
path('logout', views.UserLogoutAPIView, name = 'UserLogout'),
path('profile', views.ProfileInfoAPIView, name = 'ProfileInfo'),
path('activate/<uidb64>/<token>', views.UserActivationAPIView, name = 'UserActivation'),
path('reset_password_request', views.UserResetPasswordRequestAPIView, name = 'UserResetPasswordRequest'),
path('reset_password/<uidb64>/<token>', views.UserResetPasswordAPIView, name = 'UserResetPassword'),

View File

@ -10,7 +10,7 @@ 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, GameListSerializer, TeamSerializer, CurrentCheckPointSerializer, CheckPointCoordinatesSerializer
from .serializers import UserRegisterSerializer, UserResetPasswordSerializer, UserPasswordSerializer, GameListSerializer, TeamSerializer, CurrentCheckPointSerializer, CheckPointCoordinatesSerializer, ProfileInfoSerializer
from django.utils.html import strip_tags
from django.contrib.auth.password_validation import validate_password
from django_filters.rest_framework import DjangoFilterBackend
@ -47,10 +47,27 @@ class ListGamesAPIView(generics.ListAPIView):
def get_queryset(self):
profile = Profile.objects.get(user = self.request.user)
if(self.kwargs['visited'] == '0'):
data = list(map(lambda team_i: team_i.game,filter(lambda ob:not Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all())))
else:
data = list(map(lambda team_i: team_i.game,filter(lambda ob:Gamer.objects.filter(profile = profile, team = ob).exists(), Team.objects.all())))
data = []
for game_i in Game.objects.filter(active = True):
teams = game_i.teams.all()
if(self.kwargs['visited'] == '0'):
test = True
for team_i in teams:
gamer_i = Gamer.objects.filter(team = team_i, profile = profile)
if(gamer_i.exists()):
test = False
break
if(test):
data.append(game_i)
else:
test = False
for team_i in teams:
gamer_i = Gamer.objects.filter(team = team_i, profile = profile)
if(gamer_i.exists()):
test = True
break
if(test):
data.append(game_i)
if(len(data)!=0):
return list_to_queryset(data)
else:
@ -299,6 +316,13 @@ def UserResetPasswordAPIView(request, uidb64, token):
return Response({'ok':False, 'error':'User does not exist'}, status = status.HTTP_400_BAD_REQUEST)
return Response({'ok':False, 'error':serializer.errors}, status = status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def ProfileInfoAPIView(request):
profile = Profile.objects.get(user = request.user)
serializer = ProfileInfoSerializer(profile)
return Response({'ok':True, **serializer.data}, status = status.HTTP_200_OK)
@api_view(['POST'])
@permission_classes([permissions.IsAuthenticated])
def UserLogoutAPIView(request):

15
backend/entrypoint.sh Normal file
View File

@ -0,0 +1,15 @@
#!/bin/sh
echo "Waiting for postgres..."
while ! nc -z db 5432; do
sleep 0.1
done
echo "PostgreSQL started"
python manage.py makemigrations --noinput
python manage.py migrate --no-input
python manage.py collectstatic --no-input
exec "$@"

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

21
docker-compose.yml Normal file
View File

@ -0,0 +1,21 @@
version: '3.7'
services:
web:
build: ./backend
command: gunicorn Ugra_hackaton.wsgi:application --bind 0.0.0.0:8005
volumes:
- .:/usr/src/app/
ports:
- 8005:8005
env_file:
- ./.env
depends_on:
- db
db:
image: postgres:alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env
volumes:
postgres_data: