573 lines
21 KiB
Python
573 lines
21 KiB
Python
import uuid
|
|
from django.db import IntegrityError
|
|
from django.core.mail import send_mail
|
|
from django.conf import settings
|
|
from django.urls import reverse
|
|
|
|
from django.db import transaction
|
|
from rest_framework import serializers
|
|
from rest_framework_gis.serializers import GeoFeatureModelSerializer
|
|
from sqlalchemy.sql.functions import mode
|
|
from .models import Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, UserTracks, GoalImages, CheckinImages,CustomUser,NewEvent,NewEvent2, Team, NewCategory, Category, Entry, Member, TempUser,EntryMember
|
|
from drf_extra_fields.fields import Base64ImageField
|
|
|
|
#from django.contrib.auth.models import User
|
|
from .models import CustomUser
|
|
from django.contrib.auth import authenticate
|
|
from .utils import send_activation_email
|
|
|
|
from .models import TestModel
|
|
import logging
|
|
from django.shortcuts import get_object_or_404
|
|
from django.utils import timezone
|
|
from datetime import datetime, date
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class LocationCatSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model=Location
|
|
fields=['category',]
|
|
|
|
|
|
class LocationSerializer(GeoFeatureModelSerializer):
|
|
class Meta:
|
|
model=Location
|
|
geo_field='geom'
|
|
fields="__all__"
|
|
|
|
|
|
class Location_lineSerializer(GeoFeatureModelSerializer):
|
|
class Meta:
|
|
model=Location_line
|
|
geo_field='geom'
|
|
fields="__all__"
|
|
|
|
class Location_polygonSerializer(GeoFeatureModelSerializer):
|
|
class Meta:
|
|
model=Location_polygon
|
|
geo_field='geom'
|
|
fields="__all__"
|
|
|
|
|
|
class JPN_main_perfSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model=JpnAdminMainPerf
|
|
fields=['id', 'adm0_en', 'adm0_ja', 'adm0_pcode', 'adm1_en', 'adm1_ja', 'adm1_pcode']
|
|
|
|
# class JPN_sub_perSerializer(serializers.ModelSerializer):
|
|
# class Meta:
|
|
# model=JpnSubPerf
|
|
# fields=['id', 'adm0_en', 'adm0_ja', 'adm0_pcode', 'adm1_en', 'adm1_ja', 'adm1_pcode', 'adm2_ja', 'adm2_en', 'adm2_pcode']
|
|
|
|
|
|
# class JPN_perfSerializer(serializers.ModelSerializer):
|
|
# class Meta:
|
|
# model=JpnAdminPerf
|
|
# fields=['id','et_id', 'et_right', 'et_left', 'adm2_l', 'adm1_l', 'adm0_l', 'adm0_r', 'adm1_r', 'adm2_r', 'admlevel']
|
|
|
|
|
|
class GifuAreaSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model= GifuAreas
|
|
fields=['id', 'adm0_ja', 'adm0_pcode', 'adm1_en', 'adm1_ja', 'adm1_pcode', 'adm2_ja', 'adm2_en', 'adm2_pcode', 'area_nm']
|
|
|
|
|
|
|
|
class CreateUserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ('email', 'password')
|
|
extra_kwargs = {'password': {'write_only': True}}
|
|
|
|
def create(self, validated_data):
|
|
user = CustomUser.objects.create_user(validated_data['email'],validated_data['password'], '大垣-初心者','','')
|
|
return user
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ('id','email', 'is_rogaining' ,'group', 'zekken_number', 'event_code', 'team_name')
|
|
|
|
class GolaImageSerializer(serializers.ModelSerializer):
|
|
goalimage = Base64ImageField(max_length=None, use_url=True)
|
|
class Meta:
|
|
model = GoalImages
|
|
fields="__all__"
|
|
|
|
def get_goalimage_url(self, car):
|
|
request = self.context.get('request')
|
|
photo_url = GoalImages.goalimage.url
|
|
return request.build_absolute_uri(photo_url)
|
|
|
|
class CheckinImageSerializer(serializers.ModelSerializer):
|
|
checkinimage = Base64ImageField(max_length=None, use_url=True)
|
|
class Meta:
|
|
model = CheckinImages
|
|
fields="__all__"
|
|
|
|
def get_checkinimage_url(self, car):
|
|
request = self.context.get('request')
|
|
photo_url = CheckinImages.checkinimage.url
|
|
return request.build_absolute_uri(photo_url)
|
|
|
|
|
|
class RogUserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = RogUser
|
|
fields = ('id','user', 'paid',)
|
|
|
|
|
|
class LoginUserSerializer(serializers.Serializer):
|
|
email = serializers.CharField()
|
|
password = serializers.CharField()
|
|
|
|
def validate(self, data):
|
|
user = authenticate(**data)
|
|
if user and user.is_active:
|
|
return user
|
|
raise serializers.ValidationError("Invalid Details.")
|
|
|
|
|
|
class UseractionsSerializer(serializers.ModelSerializer):
|
|
|
|
user = UserSerializer(read_only=True)
|
|
#location = LocationSerializer(read_only=True)
|
|
location = serializers.RelatedField(source='Location', read_only=True)
|
|
#location = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
|
|
|
class Meta:
|
|
model = Useractions
|
|
fields = ('id', 'user', 'location', 'wanttogo', 'like', 'checkin', 'order',)
|
|
|
|
class UserDestinationSerializer(serializers.ModelSerializer):
|
|
|
|
#user = UserSerializer(read_only=True)
|
|
location = LocationSerializer(read_only=True)
|
|
#location = serializers.RelatedField(source='Location', read_only=True)
|
|
#location = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
|
|
|
|
class Meta:
|
|
model = Useractions
|
|
fields = ('id', 'user', 'location', 'wanttogo', 'like', 'checkin')
|
|
|
|
class LocationEventNameSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Location
|
|
fields = ('id', 'event_name',)
|
|
|
|
|
|
class UserTracksSerializer(GeoFeatureModelSerializer):
|
|
user_id = serializers.IntegerField()
|
|
class Meta:
|
|
model=UserTracks
|
|
geo_field = 'geom'
|
|
fields = ["user_id",]
|
|
|
|
def create(self, validated_data):
|
|
user_id = validated_data.pop("user_id", None)
|
|
user = CustomUser.objects.get(id=user_id)
|
|
return UserTracks.objects.create(user=user, **validated_data)
|
|
|
|
|
|
class TestSerialiser(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
model = TestModel
|
|
fields = ('id', 'testbane', 'wanttogo', 'like', 'checkin')
|
|
|
|
|
|
class ChangePasswordSerializer(serializers.Serializer):
|
|
model = CustomUser
|
|
|
|
"""
|
|
Serializer for password change endpoint.
|
|
"""
|
|
old_password = serializers.CharField(required=True)
|
|
new_password = serializers.CharField(required=True)
|
|
|
|
|
|
class RegistrationSerializer(serializers.ModelSerializer):
|
|
password2 = serializers.CharField(style={"input_type": "password"}, write_only=True)
|
|
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ['email', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'password', 'password2']
|
|
extra_kwargs = {
|
|
'password': {'write_only': True}
|
|
}
|
|
|
|
def save(self):
|
|
user = CustomUser(email=self.validated_data['email'], is_rogaining=self.validated_data['is_rogaining'], zekken_number=self.validated_data['zekken_number'], event_code=self.validated_data['event_code'], team_name=self.validated_data['team_name'], group=self.validated_data['group'])
|
|
password = self.validated_data['password']
|
|
password2 = self.validated_data['password2']
|
|
if password != password2:
|
|
raise serializers.ValidationError({'password': 'Passwords must match.'})
|
|
user.set_password(password)
|
|
user.save()
|
|
return user
|
|
|
|
class NewCategorySerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = NewCategory
|
|
#fields = ['id','category_name', 'category_number', 'duration', 'num_of_member', 'family', 'female']
|
|
fields = ['id','category_name', 'category_number']
|
|
|
|
class NewEvent2Serializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = NewEvent2
|
|
fields = ['id','event_name', 'start_datetime', 'end_datetime']
|
|
|
|
class NewEventSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = NewEvent
|
|
fields = ['event_name', 'start_datetime', 'end_datetime']
|
|
|
|
class TeamSerializer(serializers.ModelSerializer):
|
|
category = serializers.PrimaryKeyRelatedField(queryset=NewCategory.objects.all())
|
|
|
|
#category = serializers.IntegerField()
|
|
#category = NewCategorySerializer(read_only=True)
|
|
#category_id = serializers.PrimaryKeyRelatedField(
|
|
# queryset=NewCategory.objects.all(),
|
|
# source='category',
|
|
# write_only=True
|
|
#)
|
|
owner = serializers.PrimaryKeyRelatedField(read_only=True)
|
|
|
|
|
|
class Meta:
|
|
model = Team
|
|
fields = ['id','zekken_number', 'team_name', 'category', 'owner']
|
|
read_only_fields = ['id', 'owner', 'zekken_number']
|
|
|
|
def to_representation(self, instance):
|
|
ret = super().to_representation(instance)
|
|
if instance.category:
|
|
ret['category'] = {
|
|
'id': instance.category.id,
|
|
'category_name': instance.category.category_name,
|
|
'category_number': instance.category.category_number
|
|
}
|
|
else:
|
|
ret['category'] = None
|
|
ret['owner'] = CustomUserSerializer(instance.owner).data
|
|
return ret
|
|
|
|
def validate_category(self, value):
|
|
if not isinstance(value, NewCategory):
|
|
raise serializers.ValidationError("Invalid category")
|
|
return value
|
|
|
|
#if not NewCategory.objects.filter(id=value).exists():
|
|
# raise serializers.ValidationError("Invalid category ID")
|
|
#return value
|
|
|
|
|
|
def create(self, validated_data):
|
|
return Team.objects.create(**validated_data)
|
|
|
|
#category_id = validated_data.pop('category')
|
|
#category = get_object_or_404(NewCategory, id=category_id)
|
|
#team = Team.objects.create(category=category, **validated_data)
|
|
#team.category = category
|
|
#return team
|
|
|
|
|
|
#category = validated_data.pop('category')
|
|
#team = Team.objects.create(category=category, **validated_data)
|
|
#return team
|
|
|
|
#logger.debug(f"Creating team with data: {validated_data}")
|
|
#validated_data['owner'] = self.context['request'].user
|
|
#return super().create(validated_data)
|
|
|
|
def update(self, instance, validated_data):
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
instance.save()
|
|
return instance
|
|
|
|
#if 'category' in validated_data:
|
|
# category_id = validated_data.pop('category')
|
|
# category = get_object_or_404(NewCategory, id=category_id)
|
|
# instance.category = category
|
|
#return super().update(instance, validated_data)
|
|
|
|
#if 'category' in validated_data:
|
|
# instance.category = validated_data.pop('category')
|
|
#return super().update(instance, validated_data)
|
|
|
|
class CategorySerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Category
|
|
fields = ['category_name', 'category_number', 'duration', 'num_of_member', 'family', 'female']
|
|
|
|
class EntrySerializer(serializers.ModelSerializer):
|
|
team = serializers.PrimaryKeyRelatedField(queryset=Team.objects.all())
|
|
event = serializers.PrimaryKeyRelatedField(queryset=NewEvent2.objects.all())
|
|
category = serializers.PrimaryKeyRelatedField(queryset=NewCategory.objects.all())
|
|
owner = serializers.PrimaryKeyRelatedField(read_only=True)
|
|
date = serializers.DateTimeField(input_formats=['%Y-%m-%d'])
|
|
|
|
#date = serializers.DateTimeField(default_timezone=timezone.get_current_timezone())
|
|
|
|
|
|
class Meta:
|
|
model = Entry
|
|
fields = ['id','team', 'event', 'category', 'date','owner']
|
|
read_only_fields = ['id','owner']
|
|
|
|
def validate_date(self, value):
|
|
if isinstance(value, str):
|
|
try:
|
|
value = datetime.strptime(value, "%Y-%m-%d")
|
|
except ValueError:
|
|
raise serializers.ValidationError("Invalid date format. Use YYYY-MM-DD.")
|
|
|
|
if isinstance(value, date):
|
|
value = datetime.combine(value, datetime.min.time())
|
|
|
|
if timezone.is_naive(value):
|
|
return timezone.make_aware(value, timezone.get_current_timezone())
|
|
return value
|
|
|
|
|
|
#if isinstance(value, date):
|
|
# # dateオブジェクトをdatetimeオブジェクトに変換
|
|
# value = datetime.combine(value, datetime.min.time())
|
|
|
|
#if timezone.is_naive(value):
|
|
# return timezone.make_aware(value, timezone.get_current_timezone())
|
|
#return value
|
|
|
|
def validate_team(self, value):
|
|
if not value.members.exists():
|
|
raise serializers.ValidationError("チームにメンバーが登録されていません。")
|
|
return value
|
|
|
|
def validate_date(self, value):
|
|
if isinstance(value, datetime):
|
|
return value.date()
|
|
return value
|
|
|
|
def validate(self, data):
|
|
team = data.get('team')
|
|
event = data.get('event')
|
|
category = data.get('category')
|
|
entry_date = data.get('date')
|
|
owner = self.context['request'].user
|
|
|
|
# Check if team, event, and category exist
|
|
if not Team.objects.filter(id=team.id).exists():
|
|
raise serializers.ValidationError("指定されたチームは存在しません。")
|
|
if not NewEvent2.objects.filter(id=event.id).exists():
|
|
raise serializers.ValidationError("指定されたイベントは存在しません。")
|
|
if not NewCategory.objects.filter(id=category.id).exists():
|
|
raise serializers.ValidationError("指定されたカテゴリーは存在しません。")
|
|
|
|
# Check for unique constraint
|
|
if Entry.objects.filter(team=team, event=event, date__date=entry_date, owner=owner).exists():
|
|
raise serializers.ValidationError("既に登録済みです。")
|
|
|
|
return data
|
|
|
|
def to_internal_value(self, data):
|
|
# dateフィールドが文字列で来た場合の処理
|
|
if 'date' in data and isinstance(data['date'], str):
|
|
try:
|
|
# 文字列をdatetimeオブジェクトに変換
|
|
data['date'] = datetime.strptime(data['date'], "%Y-%m-%d")
|
|
except ValueError:
|
|
raise serializers.ValidationError({"date": "無効な日付形式です。YYYY-MM-DD形式を使用してください。"})
|
|
|
|
return super().to_internal_value(data)
|
|
|
|
def to_representation(self, instance):
|
|
ret = super().to_representation(instance)
|
|
if isinstance(ret['date'], datetime):
|
|
ret['date'] = ret['date'].date().isoformat()
|
|
return ret
|
|
|
|
#def to_representation(self, instance):
|
|
# ret = super().to_representation(instance)
|
|
# ret['team'] = instance.team.team_name
|
|
# ret['event'] = instance.event.event_name
|
|
# ret['category'] = instance.category.category_name
|
|
# ret['owner'] = instance.owner.email
|
|
# return ret
|
|
|
|
class CustomUserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = CustomUser
|
|
#fields = ['email', 'is_staff', 'is_active', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female']
|
|
fields = ['id','email', 'firstname', 'lastname', 'date_of_birth', 'female']
|
|
read_only_fields = ['email']
|
|
|
|
class TeamDetailSerializer(serializers.ModelSerializer):
|
|
category = NewCategorySerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = Team
|
|
fields = ['id', 'zekken_number', 'team_name', 'category']
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ['id','email', 'firstname', 'lastname', 'date_of_birth', 'female', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group']
|
|
read_only_fields = ('id', 'email')
|
|
|
|
class UserUpdateSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = CustomUser
|
|
fields = ['firstname', 'lastname', 'date_of_birth', 'female']
|
|
extra_kwargs = {'email': {'read_only': True}}
|
|
|
|
def update(self, instance, validated_data):
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
instance.save()
|
|
return instance
|
|
|
|
class MemberCreationSerializer(serializers.Serializer):
|
|
#email = serializers.EmailField()
|
|
email = serializers.EmailField(allow_blank=True, required=False)
|
|
|
|
firstname = serializers.CharField(required=False)
|
|
lastname = serializers.CharField(required=False)
|
|
date_of_birth = serializers.DateField(required=False)
|
|
female = serializers.BooleanField(required=False)
|
|
|
|
|
|
class MemberWithUserSerializer(serializers.ModelSerializer):
|
|
user = UserSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = Member
|
|
fields = ['user', 'team']
|
|
|
|
class MemberSerializer(serializers.ModelSerializer):
|
|
user = CustomUserSerializer(read_only=True)
|
|
team = TeamDetailSerializer(read_only=True)
|
|
|
|
#email = serializers.EmailField(write_only=True, required=False)
|
|
#firstname = serializers.CharField(write_only=True, required=False)
|
|
#lastname = serializers.CharField(write_only=True, required=False)
|
|
#date_of_birth = serializers.DateField(write_only=True, required=False)
|
|
#female = serializers.BooleanField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = Member
|
|
fields = ['id','user','team'] # ,'email','firstname','lastname','date_of_birth','female']
|
|
read_only_fields = ['id', 'team']
|
|
|
|
|
|
'''
|
|
def create(self, validated_data):
|
|
team = validated_data['team']
|
|
email = validated_data.get('email')
|
|
|
|
if email.startswith('dummy_'):
|
|
user, _ = CustomUser.objects.get_or_create(
|
|
email=email,
|
|
defaults={**user_data, 'is_active': True}
|
|
)
|
|
else:
|
|
user, _ = CustomUser.objects.get_or_create(
|
|
email=email,
|
|
defaults={**user_data, 'is_active': False}
|
|
)
|
|
|
|
member = Member.objects.create(user=user, **validated_data)
|
|
return member
|
|
'''
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
user_data = validated_data.pop('user', {})
|
|
user = instance.user
|
|
|
|
if user.email.startswith('dummy_'): # dummy_ で始まるメールアドレスの場合のみ更新
|
|
for attr, value in user_data.items():
|
|
setattr(user, attr, value)
|
|
user.save()
|
|
else:
|
|
raise serializers.ValidationError("このユーザーの情報は更新できません。")
|
|
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
|
|
class EntryMemberSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = EntryMember
|
|
fields = ['id', 'entry', 'member', 'is_temporary']
|
|
|
|
|
|
class TempUserSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = TempUser
|
|
fields = ['id','email', 'password', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female', 'verification_code', 'created_at', 'expires_at']
|
|
|
|
class EntryCreationSerializer(serializers.Serializer):
|
|
owner_email = serializers.EmailField()
|
|
event_name = serializers.CharField()
|
|
category_name = serializers.CharField()
|
|
team_name = serializers.CharField()
|
|
zekken_number = serializers.CharField()
|
|
date = serializers.DateField()
|
|
members = serializers.ListField(child=serializers.DictField())
|
|
|
|
def create(self, validated_data):
|
|
owner = CustomUser.objects.get(email=validated_data['owner_email'])
|
|
event = NewEvent2.objects.get(event_name=validated_data['event_name'])
|
|
category = NewCategory.objects.get(category_name=validated_data['category_name'])
|
|
|
|
# Create or get team
|
|
team, _ = Team.objects.get_or_create(
|
|
zekken_number=validated_data['zekken_number'],
|
|
category=category,
|
|
defaults={'team_name': validated_data['team_name'], 'owner': owner}
|
|
)
|
|
|
|
# Create or update entry
|
|
entry, _ = Entry.objects.update_or_create(
|
|
owner=owner,
|
|
team=team,
|
|
event=event,
|
|
date=validated_data['date'],
|
|
defaults={'category': category}
|
|
)
|
|
|
|
# Process members
|
|
for member_data in validated_data['members']:
|
|
user, created = CustomUser.objects.get_or_create(
|
|
email=member_data.get('email'),
|
|
defaults={
|
|
'firstname': member_data['firstname'],
|
|
'lastname': member_data['lastname'],
|
|
'date_of_birth': member_data['date_of_birth']
|
|
}
|
|
)
|
|
|
|
if created:
|
|
TempUser.objects.create(
|
|
email=user.email,
|
|
firstname=user.firstname,
|
|
lastname=user.lastname,
|
|
date_of_birth=user.date_of_birth
|
|
)
|
|
# Send invitation email here
|
|
|
|
member, _ = NewMember.objects.get_or_create(
|
|
user=user,
|
|
team=team,
|
|
defaults={'is_temporary': created}
|
|
)
|
|
|
|
EntryMember.objects.get_or_create(entry=entry, member=member)
|
|
|
|
return entry
|
|
|
|
|