debugging entry

This commit is contained in:
2024-07-25 00:57:48 +00:00
parent 09e39987e2
commit c0fb177d02
24 changed files with 1051 additions and 395 deletions

View File

@ -4,7 +4,7 @@ from django.shortcuts import render
from leaflet.admin import LeafletGeoAdmin
from leaflet.admin import LeafletGeoAdminMixin
from leaflet_admin_list.admin import LeafletAdminListMixin
from .models import RogUser, Location, SystemSettings, JoinedEvent, Favorite, TravelList, TravelPoint, ShapeLayers, Event, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, CustomUser, GifuAreas, UserTracks, templocation, UserUpload, EventUser, GoalImages, CheckinImages, NewEvent, Team, Category, Entry, Member, TempUser
from .models import RogUser, Location, SystemSettings, JoinedEvent, Favorite, TravelList, TravelPoint, ShapeLayers, Event, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, CustomUser, GifuAreas, UserTracks, templocation, UserUpload, EventUser, GoalImages, CheckinImages, NewEvent, NewEvent2, Team, NewCategory, Category, Entry, Member, TempUser
from django.contrib.auth.admin import UserAdmin
from django.urls import path
from django.shortcuts import render
@ -196,8 +196,8 @@ class TempLocationAdmin(LeafletGeoAdmin):
list_display = ('location_id','cp', 'location_name', 'category', 'event_name', 'event_active', 'auto_checkin', 'checkin_radius', 'checkin_point', 'buy_point',)
actions = [tranfer_to_location,]
@admin.register(NewEvent)
class NewEventAdmin(admin.ModelAdmin):
@admin.register(NewEvent2)
class NewEvent2Admin(admin.ModelAdmin):
list_display = ['event_name', 'start_datetime', 'end_datetime']
search_fields = ['event_name']
@ -206,8 +206,8 @@ class TeamAdmin(admin.ModelAdmin):
list_display = ['zekken_number', 'team_name', 'owner']
search_fields = ['zekken_number', 'team_name', 'owner__email']
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
@admin.register(NewCategory)
class NewCategoryAdmin(admin.ModelAdmin):
list_display = ['category_name', 'category_number', 'duration', 'num_of_member', 'family', 'female']
list_filter = ['family', 'female']
search_fields = ['category_name']

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-09-09 13:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0032_alter_location_sub_loc_id'),
]
operations = [
migrations.AlterField(
model_name='templocation',
name='sub_loc_id',
field=models.CharField(blank=True, max_length=2048, null=True, verbose_name='Sub location id'),
),
]

View File

@ -0,0 +1,274 @@
# Generated by Django 3.2.9 on 2024-07-24 05:31
import datetime
from django.conf import settings
import django.contrib.postgres.indexes
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
dependencies = [
('rog', '0032_alter_location_sub_loc_id'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('category_name', models.CharField(max_length=255, primary_key=True, serialize=False)),
('category_number', models.IntegerField(unique=True)),
('duration', models.DurationField(default=datetime.timedelta(seconds=18000))),
('num_of_member', models.IntegerField(default=1)),
('family', models.BooleanField(default=False)),
('female', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='CheckinImages',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('checkinimage', models.FileField(blank=True, null=True, upload_to='checkin/%y%m%d')),
('checkintime', models.DateTimeField(verbose_name='Goal time')),
('team_name', models.CharField(max_length=255, verbose_name='Team name')),
('event_code', models.CharField(max_length=255, verbose_name='event code')),
('cp_number', models.IntegerField(verbose_name='CP numner')),
],
),
migrations.CreateModel(
name='Entry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField()),
],
),
migrations.CreateModel(
name='EntryMember',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_temporary', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='GoalImages',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('goalimage', models.FileField(blank=True, null=True, upload_to='goals/%y%m%d')),
('goaltime', models.DateTimeField(verbose_name='Goal time')),
('team_name', models.CharField(max_length=255, verbose_name='Team name')),
('event_code', models.CharField(max_length=255, verbose_name='event code')),
('cp_number', models.IntegerField(verbose_name='CP numner')),
],
),
migrations.CreateModel(
name='Member',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_temporary', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='NewEvent',
fields=[
('event_name', models.CharField(max_length=255, primary_key=True, serialize=False)),
('start_datetime', models.DateTimeField(default=django.utils.timezone.now)),
('end_datetime', models.DateTimeField()),
],
),
migrations.CreateModel(
name='Team',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('zekken_number', models.CharField(max_length=255, unique=True)),
('team_name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='TempUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=254, unique=True)),
('password', models.CharField(max_length=128)),
('is_rogaining', models.BooleanField(default=False)),
('zekken_number', models.CharField(blank=True, max_length=255, null=True)),
('event_code', models.CharField(blank=True, max_length=255, null=True)),
('team_name', models.CharField(blank=True, max_length=255, null=True)),
('group', models.CharField(max_length=255)),
('firstname', models.CharField(blank=True, max_length=255, null=True)),
('lastname', models.CharField(blank=True, max_length=255, null=True)),
('date_of_birth', models.DateField(blank=True, null=True)),
('female', models.BooleanField(default=False)),
('verification_code', models.UUIDField(default=uuid.uuid4, editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('expires_at', models.DateTimeField()),
],
),
migrations.DeleteModel(
name='JpnAdminPerf',
),
migrations.DeleteModel(
name='JpnSubPerf',
),
migrations.AddField(
model_name='customuser',
name='date_of_birth',
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='event_code',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Event Code'),
),
migrations.AddField(
model_name='customuser',
name='female',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='customuser',
name='firstname',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='customuser',
name='is_rogaining',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='customuser',
name='lastname',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='customuser',
name='team_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Team Name'),
),
migrations.AddField(
model_name='customuser',
name='zekken_number',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Zekken Number'),
),
migrations.AlterField(
model_name='customuser',
name='email',
field=models.CharField(max_length=255, unique=True, verbose_name='Email'),
),
migrations.AlterField(
model_name='location',
name='category',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Category'),
),
migrations.AlterField(
model_name='location',
name='event_active',
field=models.BooleanField(db_index=True, default=True, verbose_name='Is Event active'),
),
migrations.AlterField(
model_name='location',
name='event_name',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Event name'),
),
migrations.AlterField(
model_name='location',
name='group',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Group'),
),
migrations.AlterField(
model_name='location',
name='location_id',
field=models.IntegerField(blank=True, db_index=True, null=True, verbose_name='Location id'),
),
migrations.AlterField(
model_name='templocation',
name='sub_loc_id',
field=models.CharField(blank=True, max_length=2048, null=True, verbose_name='Sub location id'),
),
migrations.AddIndex(
model_name='location',
index=django.contrib.postgres.indexes.GistIndex(fields=['geom'], name='rog_locatio_geom_4793cc_gist'),
),
migrations.AddField(
model_name='team',
name='category',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='rog.category'),
),
migrations.AddField(
model_name='team',
name='owner',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_teams', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='member',
name='team',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.team'),
),
migrations.AddField(
model_name='member',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='goalimages',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='entrymember',
name='entry',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.entry'),
),
migrations.AddField(
model_name='entrymember',
name='member',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.member'),
),
migrations.AddField(
model_name='entry',
name='category',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.category'),
),
migrations.AddField(
model_name='entry',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.newevent'),
),
migrations.AddField(
model_name='entry',
name='owner',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='entry',
name='team',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.team'),
),
migrations.AddField(
model_name='checkinimages',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='category',
unique_together={('category_name', 'category_number')},
),
migrations.AlterUniqueTogether(
name='team',
unique_together={('zekken_number', 'category')},
),
migrations.AlterUniqueTogether(
name='member',
unique_together={('team', 'user')},
),
migrations.AlterUniqueTogether(
name='entrymember',
unique_together={('entry', 'member')},
),
migrations.AlterUniqueTogether(
name='entry',
unique_together={('team', 'event', 'date', 'owner')},
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-06 10:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0033_alter_templocation_sub_loc_id'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='email',
field=models.CharField(max_length=255, verbose_name='user name'),
),
]

View File

@ -0,0 +1,34 @@
# Generated by Django 3.2.9 on 2024-07-24 06:22
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0033_auto_20240724_1431'),
]
operations = [
migrations.AlterField(
model_name='category',
name='category_number',
field=models.IntegerField(default=0),
),
migrations.CreateModel(
name='NewCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('category_name', models.CharField(max_length=255, unique=True)),
('category_number', models.IntegerField(default=0)),
('duration', models.DurationField(default=datetime.timedelta(seconds=18000))),
('num_of_member', models.IntegerField(default=1)),
('family', models.BooleanField(default=False)),
('female', models.BooleanField(default=False)),
],
options={
'unique_together': {('category_name', 'category_number')},
},
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-06 10:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0034_alter_customuser_email'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='email',
field=models.EmailField(max_length=254, unique=True, verbose_name='user name'),
),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 3.2.9 on 2024-07-24 06:29
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('rog', '0034_auto_20240724_1522'),
]
operations = [
migrations.CreateModel(
name='NewEvent2',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('event_name', models.CharField(max_length=255, unique=True)),
('start_datetime', models.DateTimeField(default=django.utils.timezone.now)),
('end_datetime', models.DateTimeField()),
],
),
migrations.AlterField(
model_name='entry',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.newevent2'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-06 11:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0035_alter_customuser_email'),
]
operations = [
migrations.AlterField(
model_name='customuser',
name='email',
field=models.CharField(max_length=255, unique=True, verbose_name='Email'),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.9 on 2024-07-24 06:58
from django.db import migrations, models
import django.db.models.deletion
import rog.models
class Migration(migrations.Migration):
dependencies = [
('rog', '0035_auto_20240724_1529'),
]
operations = [
migrations.AlterField(
model_name='team',
name='category',
field=models.ForeignKey(default=rog.models.get_default_category, on_delete=django.db.models.deletion.SET_DEFAULT, to='rog.newcategory'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.9 on 2024-07-24 15:20
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rog', '0036_alter_team_category'),
]
operations = [
migrations.AlterField(
model_name='member',
name='team',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='members', to='rog.team'),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-06 13:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0036_alter_customuser_email'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='is_rogaining',
field=models.BooleanField(default=False),
),
]

View File

@ -1,28 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-16 10:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0037_customuser_is_rogaining'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='event_code',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Event Code'),
),
migrations.AddField(
model_name='customuser',
name='team_name',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Team Name'),
),
migrations.AddField(
model_name='customuser',
name='zekken_number',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Zekken Number'),
),
]

View File

@ -1,27 +0,0 @@
# Generated by Django 3.2.9 on 2022-10-17 11:39
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rog', '0038_auto_20221016_1950'),
]
operations = [
migrations.CreateModel(
name='GoalImages',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('goalimage', models.FileField(blank=True, null=True, upload_to='%y%m%d')),
('goaltime', models.DateTimeField(verbose_name='Goal time')),
('team_name', models.CharField(max_length=255, verbose_name='Team name')),
('event_code', models.CharField(max_length=255, verbose_name='event code')),
('cp_number', models.IntegerField(verbose_name='CP numner')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -1,32 +0,0 @@
# Generated by Django 3.2.9 on 2022-11-05 10:39
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('rog', '0039_goalimages'),
]
operations = [
migrations.AlterField(
model_name='goalimages',
name='goalimage',
field=models.FileField(blank=True, null=True, upload_to='goals/%y%m%d'),
),
migrations.CreateModel(
name='CheckinImages',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('checkinimage', models.FileField(blank=True, null=True, upload_to='checkin/%y%m%d')),
('checkintime', models.DateTimeField(verbose_name='Goal time')),
('team_name', models.CharField(max_length=255, verbose_name='Team name')),
('event_code', models.CharField(max_length=255, verbose_name='event code')),
('cp_number', models.IntegerField(verbose_name='CP numner')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -1,49 +0,0 @@
# Generated by Django 3.2.9 on 2023-05-26 08:24
import django.contrib.postgres.indexes
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0040_auto_20221105_1939'),
]
operations = [
migrations.DeleteModel(
name='JpnAdminPerf',
),
migrations.DeleteModel(
name='JpnSubPerf',
),
migrations.AlterField(
model_name='location',
name='category',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Category'),
),
migrations.AlterField(
model_name='location',
name='event_active',
field=models.BooleanField(db_index=True, default=True, verbose_name='Is Event active'),
),
migrations.AlterField(
model_name='location',
name='event_name',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Event name'),
),
migrations.AlterField(
model_name='location',
name='group',
field=models.CharField(blank=True, db_index=True, max_length=2048, null=True, verbose_name='Group'),
),
migrations.AlterField(
model_name='location',
name='location_id',
field=models.IntegerField(blank=True, db_index=True, null=True, verbose_name='Location id'),
),
migrations.AddIndex(
model_name='location',
index=django.contrib.postgres.indexes.GistIndex(fields=['geom'], name='rog_locatio_geom_4793cc_gist'),
),
]

View File

@ -1,113 +0,0 @@
# Generated by Django 3.2.9 on 2024-07-22 07:03
import datetime
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
dependencies = [
('rog', '0041_auto_20230526_1724'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('category_name', models.CharField(max_length=255, primary_key=True, serialize=False)),
('category_number', models.IntegerField(unique=True)),
('duration', models.DurationField(default=datetime.timedelta(seconds=18000))),
('num_of_member', models.IntegerField(default=1)),
('family', models.BooleanField(default=False)),
('female', models.BooleanField(default=False)),
],
options={
'unique_together': {('category_name', 'category_number')},
},
),
migrations.CreateModel(
name='NewEvent',
fields=[
('event_name', models.CharField(max_length=255, primary_key=True, serialize=False)),
('start_datetime', models.DateTimeField(default=django.utils.timezone.now)),
('end_datetime', models.DateTimeField()),
],
),
migrations.CreateModel(
name='TempUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=254, unique=True)),
('password', models.CharField(max_length=128)),
('is_rogaining', models.BooleanField(default=False)),
('zekken_number', models.CharField(blank=True, max_length=255, null=True)),
('event_code', models.CharField(blank=True, max_length=255, null=True)),
('team_name', models.CharField(blank=True, max_length=255, null=True)),
('group', models.CharField(max_length=255)),
('firstname', models.CharField(blank=True, max_length=255, null=True)),
('lastname', models.CharField(blank=True, max_length=255, null=True)),
('date_of_birth', models.DateField(blank=True, null=True)),
('female', models.BooleanField(default=False)),
('verification_code', models.UUIDField(default=uuid.uuid4, editable=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('expires_at', models.DateTimeField()),
],
),
migrations.AddField(
model_name='customuser',
name='date_of_birth',
field=models.DateField(blank=True, null=True),
),
migrations.AddField(
model_name='customuser',
name='female',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='customuser',
name='firstname',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.AddField(
model_name='customuser',
name='lastname',
field=models.CharField(blank=True, max_length=255, null=True),
),
migrations.CreateModel(
name='Team',
fields=[
('zekken_number', models.CharField(max_length=255, primary_key=True, serialize=False)),
('team_name', models.CharField(max_length=255)),
('password', models.CharField(max_length=128)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Member',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.team')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'unique_together': {('team', 'user')},
},
),
migrations.CreateModel(
name='Entry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField()),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.category')),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.newevent')),
('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='rog.team')),
],
options={
'unique_together': {('team', 'event', 'date')},
},
),
]

View File

@ -261,6 +261,15 @@ class TempUser(models.Model):
def is_valid(self):
return timezone.now() <= self.expires_at
class NewEvent2(models.Model):
event_name = models.CharField(max_length=255, unique=True)
start_datetime = models.DateTimeField(default=timezone.now)
end_datetime = models.DateTimeField()
def __str__(self):
return f"{self.event_name} - From:{self.start_datetime} To:{self.end_datetime}"
class NewEvent(models.Model):
event_name = models.CharField(max_length=255, primary_key=True)
start_datetime = models.DateTimeField(default=timezone.now)
@ -269,19 +278,27 @@ class NewEvent(models.Model):
def __str__(self):
return f"{self.event_name} - From:{self.start_datetime} To:{self.end_datetime}"
def get_default_category():
return NewCategory.objects.get_or_create(category_name="Default Category", category_number=1)[0].id
class Team(models.Model):
zekken_number = models.CharField(max_length=255, primary_key=True)
zekken_number = models.CharField(max_length=255, unique=True)
team_name = models.CharField(max_length=255)
password = models.CharField(max_length=128)
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name='owned_teams', blank=True, null=True)
category = models.ForeignKey('NewCategory', on_delete=models.SET_DEFAULT, default=get_default_category)
class Meta:
unique_together = ('zekken_number', 'category')
def __str__(self):
return f"{self.zekken_number} - {self.team_name}, owner:{self.owner.lastname} {self.owner.firstname}"
class Member(models.Model):
team = models.ForeignKey(Team, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='members')
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
is_temporary = models.BooleanField(default=False) # Akira 2024-7-24
class Meta:
unique_together = ('team', 'user')
@ -292,7 +309,26 @@ class Member(models.Model):
#
class Category(models.Model):
category_name = models.CharField(max_length=255, primary_key=True)
category_number = models.IntegerField(unique=True)
category_number = models.IntegerField(default=0)
duration = models.DurationField(default=timedelta(hours=5))
num_of_member = models.IntegerField(default=1)
family = models.BooleanField(default=False)
female = models.BooleanField(default=False)
class Meta:
unique_together = ('category_name','category_number')
def __str__(self):
hours = self.duration.total_seconds() // 3600
return f"{self.category_name} - {self.category_number} ({int(hours)}時間)"
@property
def hours(self):
return self.duration.total_seconds() // 3600
class NewCategory(models.Model):
category_name = models.CharField(max_length=255, unique=True)
category_number = models.IntegerField(default=0)
duration = models.DurationField(default=timedelta(hours=5))
num_of_member = models.IntegerField(default=1)
family = models.BooleanField(default=False)
@ -311,12 +347,13 @@ class Category(models.Model):
class Entry(models.Model):
team = models.ForeignKey(Team, on_delete=models.CASCADE)
event = models.ForeignKey(NewEvent, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
event = models.ForeignKey(NewEvent2, on_delete=models.CASCADE)
category = models.ForeignKey(NewCategory, on_delete=models.CASCADE)
date = models.DateTimeField()
owner = models.ForeignKey(CustomUser, on_delete=models.CASCADE,blank=True, null=True) # Akira 2024-7-24
class Meta:
unique_together = ('team', 'event', 'date')
unique_together = ('team', 'event', 'date','owner')
def __str__(self):
return f"{self.team.zekken_number} - {self.event.event_name} - {self.date}"
@ -332,9 +369,13 @@ class Entry(models.Model):
})
# メンバーの年齢と性別をチェック
members = Member.objects.filter(team=self.team)
if not members.exists():
raise ValidationError("チームにメンバーが登録されていません。")
if self.team and not self.team.members.exists():
raise ValidationError({'team': 'チームにメンバーが登録されていません。'})
#members = Member.objects.filter(team=self.team)
#if not members.exists():
# # ここで、owner をMemberに登録する。 Akira 2024-7-24
# raise ValidationError("チームにメンバーが登録されていません。")
adults = [m for m in members if self.is_adult(m.user.date_of_birth)]
children = [m for m in members if self.is_child(m.user.date_of_birth)]
@ -387,6 +428,17 @@ class Entry(models.Model):
return 13 <= age <= 17
class EntryMember(models.Model):
entry = models.ForeignKey(Entry, on_delete=models.CASCADE)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
is_temporary = models.BooleanField(default=False) # Akira 2024-7-24
class Meta:
unique_together = ('entry', 'member')
def __str__(self):
return f"{self.entry.team.zekken_number} - {self.member.user.lastname} {self.member.user.firstname}"
class GoalImages(models.Model):
user=models.ForeignKey(CustomUser, on_delete=models.DO_NOTHING)

View File

@ -1,6 +1,16 @@
from rest_framework import permissions
from .models import Team,Member
class IsMemberOrTeamOwner(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# obj は Member インスタンス
return request.user == obj.user or request.user == obj.team.owner
# Check if user is a member of the team or the team owner
return request.user in obj.team.members.all() or request.user == obj.team.owner
class IsTeamOwner(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if isinstance(obj, Team):
return obj.owner == request.user
elif isinstance(obj, Member):
return obj.team.owner == request.user
return False

View File

@ -1,15 +1,25 @@
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, Team, Category, Entry, Member, TempUser
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
logger = logging.getLogger(__name__)
class LocationCatSerializer(serializers.ModelSerializer):
class Meta:
@ -194,15 +204,67 @@ class RegistrationSerializer(serializers.ModelSerializer):
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 = 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 = ['zekken_number', 'team_name', 'password', 'owner']
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)
ret['category'] = {
'id': instance.category.id,
'category_name': instance.category.category_name,
'category_number': instance.category.category_number
}
ret['owner'] = CustomUserSerializer(instance.owner).data
return ret
def validate_category(self, value):
if not NewCategory.objects.filter(id=value.id).exists():
raise serializers.ValidationError("Invalid category ID.")
return value
def create(self, validated_data):
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):
if 'category' in validated_data:
instance.category = validated_data.pop('category')
return super().update(instance, validated_data)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
@ -210,29 +272,60 @@ class CategorySerializer(serializers.ModelSerializer):
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=NewEvent.objects.all())
category = serializers.PrimaryKeyRelatedField(queryset=NewCategory.objects.all())
owner = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Entry
fields = ['team', 'event', 'category', 'date']
fields = ['id','team', 'event', 'category', 'date','owner']
class MemberSerializer(serializers.ModelSerializer):
class Meta:
model = Member
fields = ['team', 'user']
def validate_team(self, value):
if not value.members.exists():
raise serializers.ValidationError("チームにメンバーが登録されていません。")
return value
class TempUserSerializer(serializers.ModelSerializer):
class Meta:
model = TempUser
fields = ['email', 'password', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname', 'date_of_birth', 'female', 'verification_code', 'created_at', 'expires_at']
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 = ['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 = ['email', 'firstname', 'lastname', 'date_of_birth', 'female', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group']
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 MemberWithUserSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
@ -240,3 +333,149 @@ class MemberWithUserSerializer(serializers.ModelSerializer):
class Meta:
model = Member
fields = ['user', 'team']
class MemberSerializer(serializers.ModelSerializer):
user = CustomUserSerializer()
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:
user, created = CustomUser.objects.get_or_create(email=email)
if created:
user.firstname = validated_data.get('firstname', '')
user.lastname = validated_data.get('lastname', '')
user.date_of_birth = validated_data.get('date_of_birth')
user.female = validated_data.get('female', False)
user.is_active = False
user.activation_token = str(uuid.uuid4())
user.save()
activation_link = self.context['request'].build_absolute_uri(
reverse('user-activation', kwargs={'activation_token': user.activation_token})
)
try:
send_activation_email(user, activation_link)
except Exception as e:
logger.error(f"アクティベーションメールの送信中にエラーが発生しました: {str(e)}")
# メール送信に失敗しても、ユーザー作成は続行します
else:
dummy_email = f"dummy_{uuid.uuid4()}@example.com"
user = CustomUser.objects.create(
email=dummy_email,
firstname=validated_data.get('firstname', ''),
lastname=validated_data.get('lastname', ''),
date_of_birth=validated_data.get('date_of_birth'),
female=validated_data.get('female', False),
is_active=True
)
try:
member = Member.objects.create(user=user, team=team)
except IntegrityError:
# ユーザーがすでにチームのメンバーの場合
raise serializers.ValidationError("このユーザーは既にチームのメンバーです。")
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

View File

@ -0,0 +1,16 @@
件名: アカウントのアクティベーション
{name} 様
この度は、サービスにご登録いただき、ありがとうございます。
以下のリンクをクリックしてアカウントをアクティベートしてください:
{activation_link}
また、アプリをダウンロードしてください:
{app_download_link}
このメールに心当たりがない場合は、お手数ですが破棄してください。
よろしくお願いいたします。
{service_name} チーム

View File

@ -0,0 +1,16 @@
件名: アカウントのアクティベーション
{name} 様
この度は、サービスにご登録いただき、ありがとうございます。
以下のリンクをクリックしてアカウントをアクティベートしてください:
{activation_link}
また、アプリをダウンロードしてください:
{app_download_link}
このメールに心当たりがない場合は、お手数ですが破棄してください。
よろしくお願いいたします。
{service_name} チーム

View File

@ -1,12 +1,13 @@
from sys import prefix
from rest_framework import urlpatterns
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, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView
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, TeamViewSet,MemberViewSet,EntryViewSet,RegisterView, VerifyEmailView, NewEventListView,NewEvent2ListView,NewCategoryListView,CategoryListView, MemberUserDetailView, TeamMembersWithUserView,MemberAddView,UserActivationView
from django.urls import path, include
from knox import views as knox_views
from .views import TestActionViewSet
from .views import OwnerEntriesView, OwnerTeamsView, OwnerMembersView
router = DefaultRouter()
@ -26,9 +27,14 @@ router.register(prefix='checkinimage', viewset=CheckinImageViewSet, basename='ch
# /api/entries/ - エントリーの一覧取得と作成
# /api/entries/<pk>/ - 特定のエントリーの取得、更新、削除
#
router.register(r'teams', TeamViewSet)
router.register(r'members', MemberViewSet)
router.register(r'entries', EntryViewSet)
#router.register(r'teams', TeamViewSet)
#router.register(r'members', MemberViewSet)
#router.register(r'entries', EntryViewSet)
router.register(r'entry', EntryViewSet, basename='entry')
router.register(r'teams', TeamViewSet, basename='team')
router.register(r'members', MemberViewSet, basename='member')
# Akira 追加
# GET /api/members/<member_id>/user/: 特定のメンバーのユーザー情報を取得
@ -69,9 +75,13 @@ urlpatterns += [
# path('goal-image/', GoalImageViewSet.as_view(), name='goal-image')
path('register/', RegisterView.as_view(), name='register'),
path('verify-email/<uuid:verification_code>/', VerifyEmailView.as_view(), name='verify-email'),
path('categories/', CategoryListView.as_view(), name='category-list'),
path('new-events/', NewEventListView.as_view(), name='new-event-list'),
path('categories/', NewCategoryListView.as_view(), name='category-list'),
path('new-events/', NewEvent2ListView.as_view(), name='new-event-list'),
path('members/<int:pk>/user/', MemberUserDetailView.as_view(), name='member-user-detail'),
path('teams/<int:team_id>/members-with-user/', TeamMembersWithUserView.as_view(), name='team-members-with-user'),
path('teams/<int:team_id>/members/', MemberViewSet.as_view({'get': 'list', 'post': 'create'}), name='team-members'),
path('teams/<int:team_id>/members/<int:pk>/', MemberViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}), name='team-member-detail'),
path('activate/<str:activation_token>/', UserActivationView.as_view(), name='user-activation'),
]

34
rog/utils.py Normal file
View File

@ -0,0 +1,34 @@
import os
from django.template.loader import render_to_string
from django.conf import settings
import logging
from django.core.mail import send_mail
logger = logging.getLogger(__name__)
def load_email_template(template_name, context):
template_path = os.path.join('email', template_name)
email_content = render_to_string(template_path, context)
# 件名と本文を分離
subject, _, body = email_content.partition('\n\n')
subject = subject.replace('件名: ', '').strip()
return subject, body
def send_activation_email(user, activation_link):
context = {
'name': user.firstname or user.email,
'activation_link': activation_link,
'app_download_link': settings.APP_DOWNLOAD_LINK,
'service_name': settings.SERVICE_NAME,
}
subject, body = load_email_template('activation_email.txt', context)
try:
send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
logger.info(f"アクティベーションメールを送信しました。 受信者: {user.email}")
except Exception as e:
logger.error(f"アクティベーションメールの送信に失敗しました。 受信者: {user.email}, エラー: {str(e)}")
raise # エラーを再度発生させて、呼び出し元で処理できるようにします

View File

@ -1,12 +1,28 @@
from rest_framework import serializers
from django.db import IntegrityError
from django.urls import reverse
from .utils import send_activation_email
import uuid
from rest_framework.exceptions import ValidationError as DRFValidationError
from django.db import transaction
from django.db.models import F
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from .models import Team, Member, CustomUser, NewCategory
from .serializers import TeamSerializer, MemberSerializer, CustomUserSerializer, TeamDetailSerializer,UserUpdateSerializer
from .permissions import IsTeamOwner
from curses.ascii import NUL
from django.core.serializers import serialize
from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages, NewEvent, Team, Category, Entry, Member, TempUser
from .models import GoalImages, Location, Location_line, Location_polygon, JpnAdminMainPerf, Useractions, GifuAreas, RogUser, CustomUser, UserTracks, GoalImages, CheckinImages, NewEvent,NewEvent2, Team, Category, NewCategory,Entry, Member, TempUser,EntryMember
from rest_framework import viewsets
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, MemberWithUserSerializer
from knox.models import AuthToken
from rest_framework import viewsets, generics, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import JSONParser, MultiPartParser
from .serializers import LocationSerializer
@ -14,7 +30,7 @@ from django.http import JsonResponse
from rest_framework.permissions import IsAuthenticated
from django.contrib.gis.db.models import Extent, Union
from .serializers import TestSerialiser,NewEventSerializer, TeamSerializer, CategorySerializer, EntrySerializer, MemberSerializer, TempUserSerializer, CustomUserSerializer
from .serializers import TestSerialiser,NewEventSerializer,NewEvent2Serializer, TeamSerializer, NewCategorySerializer,CategorySerializer, EntrySerializer, MemberSerializer, TempUserSerializer, CustomUserSerializer,EntryMemberSerializer,EntryCreationSerializer
from .models import TestModel
from django.shortcuts import get_object_or_404
from django.db.models import F
@ -27,13 +43,17 @@ from rest_framework.decorators import api_view
from rest_framework.decorators import api_view, permission_classes
from rest_framework.parsers import JSONParser, MultiPartParser
from django.views.decorators.csrf import csrf_exempt
import uuid
from django.shortcuts import render
from .permissions import IsMemberOrTeamOwner
from django.utils.decorators import method_decorator
from django.utils.encoding import force_str
import logging
logger = logging.getLogger(__name__)
class LocationViewSet(viewsets.ModelViewSet):
queryset=Location.objects.all()
serializer_class=LocationSerializer
@ -288,6 +308,25 @@ class LoginAPI(generics.GenericAPIView):
"token": AuthToken.objects.create(user)[1]
})
class UserUpdateAPI(generics.UpdateAPIView):
permission_classes = [permissions.IsAuthenticated]
serializer_class = UserUpdateSerializer
def get_object(self):
return self.request.user
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {}
return Response(serializer.data)
class UserAPI(generics.RetrieveAPIView):
permission_classes = [permissions.IsAuthenticated,]
serializer_class = UserSerializer
@ -509,6 +548,17 @@ def CustomAreaNames(request):
return JsonResponse(serializer.data, safe=False)
class UserActivationView(APIView):
def get(self, request, activation_token):
try:
user = CustomUser.objects.get(activation_token=activation_token, is_active=False)
user.is_active = True
user.activation_token = None
user.save()
return Response({"message": "アカウントが正常にアクティベートされました。"}, status=status.HTTP_200_OK)
except CustomUser.DoesNotExist:
return Response({"error": "無効なアクティベーショントークンです。"}, status=status.HTTP_400_BAD_REQUEST)
class ChangePasswordView(generics.UpdateAPIView):
"""
An endpoint for changing password.
@ -562,32 +612,96 @@ class RegistrationView(APIView):
# Akira
@method_decorator(csrf_exempt, name='dispatch')
class NewEvent2ViewSet(viewsets.ModelViewSet):
queryset = NewEvent2.objects.all()
serializer_class = NewEvent2Serializer
permission_classes = [IsAuthenticated]
class NewEvent2ListView(generics.ListAPIView):
queryset = NewEvent2.objects.all()
serializer_class = NewEvent2Serializer
permission_classes = [IsAuthenticated]
class NewEventViewSet(viewsets.ModelViewSet):
queryset = NewEvent.objects.all()
serializer_class = NewEventSerializer
permission_classes = [IsAuthenticated]
@method_decorator(csrf_exempt, name='dispatch')
class NewEventListView(generics.ListAPIView):
queryset = NewEvent.objects.all()
serializer_class = NewEventSerializer
permission_classes = [IsAuthenticated]
class TeamViewSet(viewsets.ModelViewSet):
queryset = Team.objects.all()
serializer_class = TeamSerializer
permission_classes = [permissions.IsAuthenticated]
permission_classes = [permissions.IsAuthenticated, IsTeamOwner]
def get_queryset(self):
return Team.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
with transaction.atomic():
category = serializer.validated_data['category']
category = NewCategory.objects.select_for_update().get(id=category.id)
zekken_number = category.category_number
category.category_number = F('category_number') + 1
category.save()
category.refresh_from_db() # F() 式の結果を評価
serializer.save(owner=self.request.user, zekken_number=zekken_number)
def destroy(self, request, *args, **kwargs):
team = self.get_object()
if team.members.exists():
return Response({"error": "チームにメンバーが残っているため削除できません。"}, status=status.HTTP_400_BAD_REQUEST)
return super().destroy(request, *args, **kwargs)
def update(self, request, *args, **kwargs):
try:
return super().update(request, *args, **kwargs)
except Exception as e:
return Response({"error": "更新に失敗しました。競合が発生した可能性があります。"}, status=status.HTTP_409_CONFLICT)
@action(detail=True, methods=['post'])
def copy(self, request, pk=None):
original_team = self.get_object()
with transaction.atomic():
category = NewCategory.objects.select_for_update().get(id=original_team.category.id)
new_zekken_number = category.category_number
category.category_number = F('category_number') + 1
category.save()
category.refresh_from_db() # F() 式の結果を評価
new_team = Team.objects.create(
zekken_number=new_zekken_number,
team_name=f"{original_team.team_name} (コピー)",
category=category,
owner=request.user
)
for member in original_team.members.all():
Member.objects.create(
team=new_team,
user=member.user
)
return Response(TeamSerializer(new_team).data, status=status.HTTP_201_CREATED)
class NewCategoryViewSet(viewsets.ModelViewSet):
queryset = NewCategory.objects.all()
serializer_class = NewCategorySerializer
permission_classes = [IsAuthenticated]
class NewCategoryListView(generics.ListAPIView):
queryset = NewCategory.objects.all()
serializer_class = NewCategorySerializer
permission_classes = [IsAuthenticated]
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
permission_classes = [IsAuthenticated]
@method_decorator(csrf_exempt, name='dispatch')
class CategoryListView(generics.ListAPIView):
queryset = Category.objects.all()
serializer_class = CategorySerializer
@ -611,16 +725,148 @@ class EntryViewSet(viewsets.ModelViewSet):
serializer_class = EntrySerializer
permission_classes = [permissions.IsAuthenticated]
def perform_create(self, serializer):
team = Team.objects.get(owner=self.request.user)
serializer.save(team=team)
#def perform_create(self, serializer):
# team = Team.objects.get(owner=self.request.user)
# serializer.save(team=team)
def get_queryset(self):
user = self.request.user
# ユーザーが所属するチームのIDを取得
team_ids = Member.objects.filter(user=user).values_list('team_id', flat=True)
# そのチームに関連するエントリーを取得
return Entry.objects.filter(team__id__in=team_ids)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
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)
except DRFValidationError as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
#except ValidationError as e:
# return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
class MemberViewSet(viewsets.ModelViewSet):
queryset = Member.objects.all()
serializer_class = MemberSerializer
permission_classes = [permissions.IsAuthenticated,IsTeamOwner]
def get_queryset(self):
team_id = self.kwargs['team_id']
return Member.objects.filter(team_id=team_id)
def create(self, request, *args, **kwargs):
team = Team.objects.get(id=self.kwargs['team_id'])
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
try:
self.perform_create(serializer)
except DRFValidationError as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
#except ValidationError as e:
# return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)
except IntegrityError:
return Response({"error": "このユーザーは既にチームのメンバーです。"}, status=status.HTTP_400_BAD_REQUEST)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
team = Team.objects.get(id=self.kwargs['team_id'])
serializer.save(team=team)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
if not instance.user.email.startswith('dummy_'):
return Response({"error": "このユーザーの情報は更新できません。"}, status=status.HTTP_400_BAD_REQUEST)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {}
return Response(serializer.data)
def perform_update(self, serializer):
serializer.save()
def get_object(self):
queryset = self.get_queryset()
member_id = self.kwargs['pk']
obj = get_object_or_404(queryset, id=member_id)
self.check_object_permissions(self.request, obj)
return obj
class OwnerEntriesView(generics.ListAPIView):
serializer_class = EntrySerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
return Entry.objects.filter(owner=user)
class OwnerTeamsView(generics.ListAPIView):
serializer_class = TeamSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
return Team.objects.filter(owner=user)
class OwnerMembersView(generics.ListAPIView):
serializer_class = MemberSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
return Member.objects.filter(team__owner=user)
class MemberAddView(APIView):
def post(self, request, team_id):
logger.info(f"Received request to add member to team {team_id}")
logger.debug(f"Request data: {request.data}")
team = get_object_or_404(Team, id=team_id)
logger.info(f"Found team: {team}")
serializer = MemberSerializer(data=request.data)
if serializer.is_valid():
logger.info("Serializer is valid")
try:
member = serializer.save(team=team)
logger.info(f"Member added successfully: {member}")
return Response(serializer.data, status=status.HTTP_201_CREATED)
except Exception as e:
logger.error(f"Error saving member: {str(e)}")
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
else:
logger.error(f"Serializer errors: {serializer.errors}")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class TempUserViewSet(viewsets.ModelViewSet):
queryset = TempUser.objects.all()
@ -639,9 +885,6 @@ class CustomUserViewSet(viewsets.ModelViewSet):
return CustomUser.objects.all()
return CustomUser.objects.filter(id=user.id)
# 追加の機能として、チームメンバーを取得するビュー
from rest_framework.decorators import action
from rest_framework.response import Response
class TeamMembersView(generics.ListAPIView):
serializer_class = MemberSerializer
@ -738,4 +981,3 @@ class TeamMembersWithUserView(generics.ListAPIView):
team_id = self.kwargs['team_id']
return Member.objects.filter(team_id=team_id).select_related('user', 'team')