2 Commits

Author SHA1 Message Date
1c7a6a1f5c Added APIs for team and members 2024-07-20 11:15:33 +09:00
f0114ef33c setup for Akiras Laptop 2024-04-22 00:08:34 +09:00
11 changed files with 420 additions and 35 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -1,5 +1,8 @@
# FROM python:3.9.9-slim-buster # FROM python:3.9.9-slim-buster
FROM osgeo/gdal:ubuntu-small-3.4.0 FROM osgeo/gdal:ubuntu-small-3.4.0
# Akira
FROM python:3.10
FROM ubuntu:latest
WORKDIR /app WORKDIR /app
@ -14,6 +17,13 @@ ARG TZ Asia/Tokyo \
RUN apt-get update -y RUN apt-get update -y
# 必要なライブラリのインストール by akira
RUN apt-get update && \
apt-get install -y software-properties-common && \
add-apt-repository ppa:ubuntugis/ppa && \
apt-get update && \
apt-get install -y gdal-bin libgdal-dev python3-gdal
# Install GDAL dependencies # Install GDAL dependencies
RUN apt-get install -y libgdal-dev g++ --no-install-recommends && \ RUN apt-get install -y libgdal-dev g++ --no-install-recommends && \
apt-get clean -y apt-get clean -y
@ -23,7 +33,7 @@ ENV CPLUS_INCLUDE_PATH=/usr/include/gdal
ENV C_INCLUDE_PATH=/usr/include/gdal ENV C_INCLUDE_PATH=/usr/include/gdal
RUN apt-get update \ RUN apt-get update \
&& apt-get -y install netcat gcc postgresql \ && apt-get -y install netcat-openbsd gcc postgresql \
&& apt-get clean && apt-get clean
RUN apt-get update \ RUN apt-get update \
@ -56,7 +66,9 @@ RUN pip install -r requirements.txt
COPY . /app COPY . /app
# Collect static files # Collect static files
RUN python manage.py collectstatic --noinput RUN python3 manage.py collectstatic --noinput
# Use Gunicorn as the entrypoint # Use Gunicorn as the entrypoint
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"] CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]

6
README.jpn Normal file
View File

@ -0,0 +1,6 @@
デプロイ:
you can just run
docker-compose up -d
will deploy it

View File

@ -173,4 +173,17 @@ LEAFLET_CONFIG = {
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'], 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication', ), 'DEFAULT_AUTHENTICATION_CLASSES': ('knox.auth.TokenAuthentication', ),
} }
# Email settings
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp-mail.outlook.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'akira.miyata@gifuai.net'
EMAIL_HOST_PASSWORD = 'SachikoMiyata@123'
# Optional: Set a default "from" address
DEFAULT_FROM_EMAIL = 'info@gifuai.net'

View File

@ -31,7 +31,7 @@ matplotlib==3.5.0
mccabe==0.6.1 mccabe==0.6.1
munch==2.5.0 munch==2.5.0
mypy-extensions==0.4.3 mypy-extensions==0.4.3
numpy==1.21.4 numpy==1.26.2
packaging==21.3 packaging==21.3
pandas==1.3.4 pandas==1.3.4
pathspec==0.9.0 pathspec==0.9.0
@ -46,11 +46,13 @@ pyparsing==3.0.6
pyproj==3.3.0 pyproj==3.3.0
python-dateutil==2.8.2 python-dateutil==2.8.2
pytz==2021.3 pytz==2021.3
rasterio==1.2.10 #rasterio==1.2.10 Akira
rasterio==1.3.10
regex==2021.11.10 regex==2021.11.10
requests==2.26.0 requests==2.26.0
Rtree==0.9.7 Rtree==0.9.7
scipy==1.7.3 #scipy==1.7.3
scipy==1.10.1
seaborn==0.11.2 seaborn==0.11.2
setuptools-scm==6.3.2 setuptools-scm==6.3.2
Shapely==1.8.0 Shapely==1.8.0

BIN
rog/.DS_Store vendored

Binary file not shown.

View File

@ -0,0 +1,16 @@
from django.core.management.base import BaseCommand
from django.utils import timezone
from rog.models import TempUser # アプリ名 'rog' を適切に変更してください
class Command(BaseCommand):
help = 'Deletes expired temporary user records'
def handle(self, *args, **options):
expired_users = TempUser.objects.filter(expires_at__lt=timezone.now())
count = expired_users.count()
expired_users.delete()
self.stdout.write(self.style.SUCCESS(f'Successfully deleted {count} expired temporary user records'))
# cron job の設定
# 0 3 * * * /path/to/your/python /path/to/your/manage.py cleanup_temp_users

View File

@ -23,6 +23,11 @@ from django.apps import apps
from django.db import transaction from django.db import transaction
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.contrib.postgres.indexes import GistIndex from django.contrib.postgres.indexes import GistIndex
from django.db import models
from django.contrib.auth.hashers import make_password
from django.utils import timezone
from datetime import timedelta
import csv import csv
import codecs import codecs
@ -61,35 +66,123 @@ def remove_bom_inplace(path):
fp.seek(-bom_length, os.SEEK_CUR) fp.seek(-bom_length, os.SEEK_CUR)
fp.truncate() fp.truncate()
#========== Akira ここから
class TempUser(models.Model):
email = models.EmailField(unique=True)
password = models.CharField(max_length=128)
is_rogaining = models.BooleanField(default=False)
zekken_number = models.CharField(max_length=255, blank=True, null=True)
event_code = models.CharField(max_length=255, blank=True, null=True)
team_name = models.CharField(max_length=255, blank=True, null=True)
group = models.CharField(max_length=255)
verification_code = models.UUIDField(default=uuid.uuid4, editable=False)
created_at = models.DateTimeField(auto_now_add=True)
expires_at = models.DateTimeField()
def __str__(self):
return self.email
def save(self, *args, **kwargs):
if not self.expires_at:
self.expires_at = timezone.now() + timedelta(hours=24) # 24時間の有効期限
super().save(*args, **kwargs)
def is_valid(self):
return timezone.now() <= self.expires_at
class Team(models.Model):
zekken_number = models.CharField(max_length=255, primary_key=True)
team_name = models.CharField(max_length=255)
password = models.CharField(max_length=128)
def __str__(self):
return f"{self.zekken_number} - {self.team_name}"
class Member(models.Model):
zekken_number = models.ForeignKey(Team, on_delete=models.CASCADE)
userid = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
class Meta:
unique_together = ('zekken_number', 'userid')
def __str__(self):
return f"{self.zekken_number} - {self.userid}"
class Entry(models.Model):
zekken_number = models.ForeignKey(Team, on_delete=models.CASCADE)
event_code = models.CharField(max_length=255)
date = models.DateField()
class Meta:
unique_together = ('zekken_number', 'event_code', 'date')
def __str__(self):
return f"{self.zekken_number} - {self.event_code} - {self.date}"
#============= Akira ここまで
class CustomUserManager(BaseUserManager): class CustomUserManager(BaseUserManager):
def create_user(self, email, password, group, event_code, team_name, **other_fields): def create_user(self, email, firstname, lastname, date_of_birth, password=None):
if not email: if not email:
raise ValueError(_("You must provide an email address")) raise ValueError(_("You must provide an email address"))
# email = self.normalize_email(email) # ユニークなuseridを生成
user=self.model(email=email, group=group, event_code=event_code, team_name=team_name, zekken_number=email, is_rogaining=True, **other_fields) userid = str(uuid.uuid4())
user.set_password(password)
user.save()
user = self.model(
email=self.normalize_email(email),
firstname=firstname,
lastname=lastname,
userid=userid,
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user return user
def create_superuser(self, email, password, group, **other_fields): def create_superuser(self, email, firstname, lastname, date_of_birth, password):
other_fields.setdefault('is_staff', True) user = self.create_user(
other_fields.setdefault('is_superuser', True) email,
other_fields.setdefault('is_active', True) firstname=firstname,
lastname=lastname,
date_of_birth=date_of_birth,
password=password,
)
user.is_staff = True
user.is_superuser = True
user.is_active = True
user.save(using=self._db)
return user
if other_fields.get('is_staff') is not True: class CustomUser(AbstractBaseUser, PermissionsMixin):
raise ValueError(_('Supperuser must assigned to staff')) email = models.EmailField(unique=True)
if other_fields.get('is_superuser') is not True: firstname = models.CharField(max_length=255)
raise ValueError(_('Supperuser must assigned to superuser=True')) lastname = models.CharField(max_length=255)
userid = models.CharField(max_length=255, unique=True)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
event_code = models.CharField(max_length=255, blank=True, null=True)
team_name = models.CharField(max_length=255, blank=True, null=True)
zekken_number = models.CharField(max_length=255, blank=True, null=True)
return self.create_user(email, password, group, **other_fields) objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname', 'userid', 'date_of_birth']
def __str__(self):
return self.email
class JpnAdminMainPerf(models.Model): class JpnAdminMainPerf(models.Model):
geom = models.MultiPolygonField(blank=True, null=True) geom = models.MultiPolygonField(blank=True, null=True)
@ -195,6 +288,26 @@ class UserUploadUser(models.Model):
class CustomUser(AbstractBaseUser, PermissionsMixin): class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
firstname = models.CharField(max_length=255)
lastname = models.CharField(max_length=255)
userid = models.CharField(max_length=255, unique=True, editable=False)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
event_code = models.CharField(max_length=255, blank=True, null=True)
team_name = models.CharField(max_length=255, blank=True, null=True)
zekken_number = models.CharField(max_length=255, blank=True, null=True)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['firstname', 'lastname', 'date_of_birth']
def __str__(self):
return self.email
class CustomUser_old(AbstractBaseUser, PermissionsMixin):
class Groups(models.TextChoices): class Groups(models.TextChoices):
GB1 = '大垣-初心者', '大垣-初心者' GB1 = '大垣-初心者', '大垣-初心者'
GB2 = '大垣-3時間', '大垣-3時間' GB2 = '大垣-3時間', '大垣-3時間'

View File

@ -1,14 +1,35 @@
from rest_framework import serializers from rest_framework import serializers
from rest_framework_gis.serializers import GeoFeatureModelSerializer from rest_framework_gis.serializers import GeoFeatureModelSerializer
from sqlalchemy.sql.functions import mode from sqlalchemy.sql.functions import mode
from .models import Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, UserTracks, GoalImages, CheckinImages,CustomUser from .models import Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, UserTracks, GoalImages, CheckinImages,CustomUser,Team, Member, Entry
from drf_extra_fields.fields import Base64ImageField from drf_extra_fields.fields import Base64ImageField
from django.contrib.auth.hashers import make_password
#from django.contrib.auth.models import User #from django.contrib.auth.models import User
from .models import CustomUser from .models import CustomUser
from django.contrib.auth import authenticate from django.contrib.auth import authenticate
from .models import TestModel from .models import TestModel
from .models import TempUser
class RegistrationSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={"input_type": "password"}, write_only=True)
class Meta:
model = TempUser
fields = ['email', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'password', 'password2']
extra_kwargs = {
'password': {'write_only': True}
}
def validate(self, attrs):
if attrs['password'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return attrs
def create(self, validated_data):
validated_data.pop('password2')
return TempUser.objects.create(**validated_data)
class LocationCatSerializer(serializers.ModelSerializer): class LocationCatSerializer(serializers.ModelSerializer):
@ -53,6 +74,38 @@ class JPN_main_perfSerializer(serializers.ModelSerializer):
# model=JpnAdminPerf # model=JpnAdminPerf
# fields=['id','et_id', 'et_right', 'et_left', 'adm2_l', 'adm1_l', 'adm0_l', 'adm0_r', 'adm1_r', 'adm2_r', 'admlevel'] # fields=['id','et_id', 'et_right', 'et_left', 'adm2_l', 'adm1_l', 'adm0_l', 'adm0_r', 'adm1_r', 'adm2_r', 'admlevel']
#============= Akira ここから
class TeamSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = ['zekken_number', 'team_name', 'password']
extra_kwargs = {'password': {'write_only': True}}
class MemberSerializer(serializers.ModelSerializer):
class Meta:
model = Member
fields = ['zekken_number', 'userid']
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = Entry
fields = ['zekken_number', 'event_code', 'date']
class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = ['email', 'firstname', 'lastname', 'userid', 'date_of_birth', 'password']
extra_kwargs = {
'password': {'write_only': True},
'userid': {'read_only': True}
}
def create(self, validated_data):
validated_data['password'] = make_password(validated_data.get('password'))
return super(CustomUserSerializer, self).create(validated_data)
#============= Akira ここまで
class GifuAreaSerializer(serializers.ModelSerializer): class GifuAreaSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -192,4 +245,4 @@ class RegistrationSerializer(serializers.ModelSerializer):
raise serializers.ValidationError({'password': 'Passwords must match.'}) raise serializers.ValidationError({'password': 'Passwords must match.'})
user.set_password(password) user.set_password(password)
user.save() user.save()
return user return user

View File

@ -1,7 +1,7 @@
from sys import prefix from sys import prefix
from rest_framework import urlpatterns from rest_framework import urlpatterns
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView from .views import LocationViewSet, Location_lineViewSet, Location_polygonViewSet, Jpn_Main_PerfViewSet, LocationsInPerf, ExtentForSubPerf, SubPerfInMainPerf, ExtentForMainPerf, LocationsInSubPerf, CatView, RegistrationAPI, LoginAPI, UserAPI, UserActionViewset, UserMakeActionViewset, UserDestinations, UpdateOrder, LocationInBound, DeleteDestination, CustomAreaLocations, GetAllGifuAreas, CustomAreaNames, userDetials, UserTracksViewSet, CatByCity, ChangePasswordView, GoalImageViewSet, CheckinImageViewSet, ExtentForLocations, DeleteAccount, PrivacyView, RegistrationView, VerifyEmailView, TeamViewSet, MemberViewSet, EntryViewSet
from django.urls import path, include from django.urls import path, include
from knox import views as knox_views from knox import views as knox_views
@ -18,6 +18,17 @@ router.register(prefix='track', viewset=UserTracksViewSet, basename='track')
router.register(prefix='goalimage', viewset=GoalImageViewSet, basename='goalimage') router.register(prefix='goalimage', viewset=GoalImageViewSet, basename='goalimage')
router.register(prefix='checkinimage', viewset=CheckinImageViewSet, basename='checkinimage') router.register(prefix='checkinimage', viewset=CheckinImageViewSet, basename='checkinimage')
#Akira 追加
# /api/teams/ - チームの一覧取得と作成
# /api/teams/<pk>/ - 特定のチームの取得、更新、削除
# /api/members/ - メンバーの一覧取得と作成
# /api/members/<pk>/ - 特定のメンバーの取得、更新、削除
# /api/entries/ - エントリーの一覧取得と作成
# /api/entries/<pk>/ - 特定のエントリーの取得、更新、削除
#
router.register(r'teams', TeamViewSet)
router.register(r'members', MemberViewSet)
router.register(r'entries', EntryViewSet)
urlpatterns = router.urls urlpatterns = router.urls
@ -48,5 +59,7 @@ urlpatterns += [
path('delete-account/', DeleteAccount, name="delete-account"), path('delete-account/', DeleteAccount, name="delete-account"),
path('privacy/', PrivacyView, name='privacy-view'), path('privacy/', PrivacyView, name='privacy-view'),
path('register', RegistrationView.as_view(), name='register'), path('register', RegistrationView.as_view(), name='register'),
path('verify-email/<uuid:verification_code>/', VerifyEmailView.as_view(), name='verify_email'),
# path('goal-image/', GoalImageViewSet.as_view(), name='goal-image') # path('goal-image/', GoalImageViewSet.as_view(), name='goal-image')
] ]

View File

@ -1,15 +1,15 @@
from curses.ascii import NUL from curses.ascii import NUL
from django.core.serializers import serialize from django.core.serializers import serialize
from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages, TempUser
from rest_framework import viewsets from rest_framework import viewsets,status
from .serializers import LocationSerializer, Location_lineSerializer, Location_polygonSerializer, JPN_main_perfSerializer, LocationCatSerializer, CreateUserSerializer, UserSerializer, LoginUserSerializer, UseractionsSerializer, UserDestinationSerializer, GifuAreaSerializer, LocationEventNameSerializer, RogUserSerializer, UserTracksSerializer, ChangePasswordSerializer, GolaImageSerializer, CheckinImageSerializer, RegistrationSerializer from .serializers import LocationSerializer, Location_lineSerializer, Location_polygonSerializer, JPN_main_perfSerializer, LocationCatSerializer, CreateUserSerializer, UserSerializer, LoginUserSerializer, UseractionsSerializer, UserDestinationSerializer, GifuAreaSerializer, LocationEventNameSerializer, RogUserSerializer, UserTracksSerializer, ChangePasswordSerializer, GolaImageSerializer, CheckinImageSerializer, RegistrationSerializer, Team, Member, Entry, CustomUserSerializer
from knox.models import AuthToken from knox.models import AuthToken
from rest_framework import viewsets, generics, status from rest_framework import viewsets, generics, status
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.parsers import JSONParser, MultiPartParser from rest_framework.parsers import JSONParser, MultiPartParser
from .serializers import LocationSerializer from .serializers import LocationSerializer, TeamSerializer, MemberSerializer, EntrySerializer
from django.http import JsonResponse from django.http import JsonResponse
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from django.contrib.gis.db.models import Extent, Union from django.contrib.gis.db.models import Extent, Union
@ -29,8 +29,9 @@ from rest_framework.parsers import JSONParser, MultiPartParser
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
import uuid import uuid
from django.shortcuts import render from django.shortcuts import render
from django.utils import timezone
from django.db import transaction
class LocationViewSet(viewsets.ModelViewSet): class LocationViewSet(viewsets.ModelViewSet):
queryset=Location.objects.all() queryset=Location.objects.all()
@ -55,6 +56,114 @@ class Jpn_Main_PerfViewSet(viewsets.ModelViewSet):
#===== AKira ここから
class CustomUserViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = CustomUserSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return CustomUser.objects.filter(id=self.request.user.id)
class TeamViewSet(viewsets.ModelViewSet):
queryset = Team.objects.all()
serializer_class = TeamSerializer
@transaction.atomic
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
# チーム登録後にエントリー登録と外部APIコールを行う
self.register_entry_and_call_external_api(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def register_entry_and_call_external_api(self, team_data):
# エントリーの登録
entry_data = {
'zekken_number': team_data['zekken_number'],
'event_code': request.data.get('event_code'), # エントリー用のevent_codeを取得
'date': request.data.get('date') # エントリー用の日付を取得
}
entry_serializer = EntrySerializer(data=entry_data)
if entry_serializer.is_valid():
entry_serializer.save()
# 外部APIへのコール
self.call_external_api(team_data, entry_data)
else:
# エントリー登録に失敗した場合のエラーハンドリング
raise serializers.ValidationError(entry_serializer.errors)
def call_external_api(self, team_data, entry_data):
external_api_url = "https://rogaining.sumasen.net/gifuroge/register_team"
payload = {
'zekken_number': team_data['zekken_number'],
'event_code': entry_data['event_code'],
'team_name': team_data['team_name'],
'class_name': team_data.get('class_name', 'Default'), # class_nameがない場合はデフォルト値を設定
'password': team_data['password']
}
try:
response = requests.post(external_api_url, data=payload)
response.raise_for_status() # エラーレスポンスの場合は例外を発生させる
# レスポンスの処理(必要に応じて)
print(f"External API response: {response.json()}")
except requests.RequestException as e:
# 外部APIコールに失敗した場合のエラーハンドリング
print(f"Failed to call external API: {str(e)}")
# ここでエラーをログに記録したり、管理者に通知したりすることができます
def get_queryset(self):
user = self.request.user
return Team.objects.filter(member__userid=user)
class MemberViewSet(viewsets.ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer
permission_classes = [IsAuthenticated]
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def get_queryset(self):
user = self.request.user
return Member.objects.filter(userid=user)
class EntryViewSet(viewsets.ModelViewSet):
queryset = Entry.objects.all()
serializer_class = EntrySerializer
permission_classes = [IsAuthenticated]
def create(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def get_queryset(self):
user = self.request.user
return Entry.objects.filter(zekken_number__member__userid=user)
#===== AKira ここまで
class UserTracksViewSet(viewsets.ModelViewSet): class UserTracksViewSet(viewsets.ModelViewSet):
queryset = UserTracks.objects.all() queryset = UserTracks.objects.all()
serializer_class = UserTracksSerializer serializer_class = UserTracksSerializer
@ -143,9 +252,10 @@ def LocationInBound(request):
if(cat): if(cat):
if is_rog: if is_rog:
if grp: if grp:
locs = Location.objects.filter(~Q(cp=0), geom__within=pl, category=cat, event_name__isnull=True, group__contains=grp) #locs = Location.objects.filter(~Q(cp=0), geom__within=pl, category=cat, event_name__isnull=True, group__contains=grp)
locs = Location.objects.filter(geom__within=pl, category=cat, event_name__isnull=True, group__contains=grp)
else: else:
locs = Location.objects.filter(~Q(cp=0), geom__within=pl, category=cat, event_name__isnull=True) locs = Location.objects.filter(geom__within=pl, category=cat, event_name__isnull=True)
else: else:
if grp: if grp:
locs = Location.objects.filter(geom__within=pl, category=cat, event_name__isnull=True, group__contains=grp, location_name__contains='観光') locs = Location.objects.filter(geom__within=pl, category=cat, event_name__isnull=True, group__contains=grp, location_name__contains='観光')
@ -154,9 +264,9 @@ def LocationInBound(request):
else: else:
if is_rog: if is_rog:
if grp: if grp:
locs = Location.objects.filter(~Q(cp=0), geom__within=pl, event_name__isnull=True, group__contains=grp) locs = Location.objects.filter(geom__within=pl, event_name__isnull=True, group__contains=grp)
else: else:
locs = Location.objects.filter(~Q(cp=0), geom__within=pl, event_name__isnull=True) locs = Location.objects.filter(geom__within=pl, event_name__isnull=True)
else: else:
if grp: if grp:
locs = Location.objects.filter(geom__within=pl, event_name__isnull=True, group__contains=grp, location_name__contains='観光') locs = Location.objects.filter(geom__within=pl, event_name__isnull=True, group__contains=grp, location_name__contains='観光')
@ -540,10 +650,57 @@ class TestActionViewSet(viewsets.ModelViewSet):
def PrivacyView(request): def PrivacyView(request):
return render(request, "rog/privacy.html") return render(request, "rog/privacy.html")
class RegistrationView(APIView): class RegistrationView_old(APIView):
def post(self, request): def post(self, request):
serializer = RegistrationSerializer(data=request.data) serializer = RegistrationSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
serializer.save() serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class RegistrationView(APIView):
def post(self, request):
serializer = RegistrationSerializer(data=request.data)
if serializer.is_valid():
temp_user = serializer.save()
verification_url = request.build_absolute_uri(
reverse('verify_email', kwargs={'verification_code': temp_user.verification_code})
)
send_mail(
'Verify your email',
f'Please click the link to verify your email: {verification_url}',
settings.DEFAULT_FROM_EMAIL,
[temp_user.email],
fail_silently=False,
)
return Response({"message": "Please check your email to complete registration."}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class VerifyEmailView(APIView):
def get(self, request, verification_code):
try:
temp_user = TempUser.objects.get(verification_code=verification_code)
if not temp_user.is_valid():
temp_user.delete()
return Response({"error": "Verification link has expired. Please register again."}, status=status.HTTP_400_BAD_REQUEST)
user = CustomUser.objects.create_user(
email=temp_user.email,
password=temp_user.password,
is_rogaining=temp_user.is_rogaining,
zekken_number=temp_user.zekken_number,
event_code=temp_user.event_code,
team_name=temp_user.team_name,
group=temp_user.group
)
temp_user.delete()
return Response({"message": "Email verified. Registration complete."}, status=status.HTTP_200_OK)
except TempUser.DoesNotExist:
return Response({"error": "Invalid verification code."}, status=status.HTTP_400_BAD_REQUEST)