Files
rogaining_srv/rog/admin.py

979 lines
42 KiB
Python
Raw Normal View History

2024-10-27 18:22:01 +00:00
import email
from django.contrib import admin
from django.shortcuts import render,redirect
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, NewEvent2, Team, NewCategory, Entry, Member, TempUser,GifurogeRegister
from django.contrib.auth.admin import UserAdmin
from django.urls import path,reverse
from django.shortcuts import render
from django import forms;
import requests
from django.http import HttpResponseRedirect
from django.utils.html import format_html
from .forms import CSVUploadForm
from .views import process_csv_upload
from django.db.models import F # F式をインポート
from django.db import transaction
from django.contrib import messages
import csv
from io import StringIO,TextIOWrapper
from datetime import timedelta
from django.contrib.auth.hashers import make_password
from datetime import datetime, date
from django.core.exceptions import ValidationError
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.utils.translation import gettext_lazy as _
2025-01-22 17:14:56 +09:00
from .services.csv_processor import EntryCSVProcessor
@admin.register(Entry)
class EntryAdmin(admin.ModelAdmin):
list_display = ['team', 'event', 'category', 'date', 'is_active']
def get_urls(self):
from django.urls import path
urls = super().get_urls()
custom_urls = [
path('upload-csv/', self.upload_csv_view, name='entry_upload_csv'),
]
return custom_urls + urls
def upload_csv_view(self, request):
processor = EntryCSVProcessor()
return processor.process_upload(request)
2024-10-27 18:22:01 +00:00
@admin.register(GifurogeRegister)
class GifurogeRegisterAdmin(admin.ModelAdmin):
list_display = ('event_code', 'time', 'owner_name', 'email', 'team_name', 'department')
change_list_template = 'admin/rog/gifurogeregister/change_list.html' # この行を追加
def find_matching_category(self, time, department):
"""
時間とdepartmentに基づいて適切なカテゴリを見つける
"""
try:
duration = timedelta(hours=time)
# 検索前の情報出力
print(f" Searching for category with parameters:")
print(f" - Duration: {duration}")
print(f" - Department: {department}")
# 利用可能なカテゴリの一覧を出力
all_categories = NewCategory.objects.all()
print(" Available categories:")
for cat in all_categories:
#print(f" - ID: {cat.id}")
print(f" - Name: {cat.category_name}")
print(f" - Duration: {cat.duration}")
print(f" - Number: {cat.category_number}")
# カテゴリ検索のクエリをログ出力
query = NewCategory.objects.filter(
duration=duration,
category_name__startswith=department
)
print(f" Query SQL: {query.query}")
# 検索結果の取得
category = query.first()
if category:
print(f" Found matching category:")
print(f" - Name: {category.category_name}")
print(f" - Duration: {category.duration}")
print(f" - Category Number: {getattr(category, 'category_number', 'N/A')}")
else:
print(" No matching category found with the following filters:")
print(f" - Duration equals: {duration}")
print(f" - Category name starts with: {department}")
return category
except Exception as e:
print(f"Error finding category: {e}")
print(f"Exception type: {type(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
return None
def create_entry_with_number(self, team, category, owner, event):
"""
カテゴリ番号をインクリメントしてエントリーを作成
"""
try:
with transaction.atomic():
# 事前バリデーション
try:
# チームメンバーの性別をチェック
if category.female:
for member in team.members.all():
print(f" Check existing member {member.user.lastname} {member.user.firstname} female:{member.user.female}")
if not member.user.female:
raise ValidationError(f"チーム '{team.team_name}' に男性メンバーが含まれているため、"
f"カテゴリー '{category.category_name}' には参加できません。")
except ValidationError as e:
print(f"Pre-validation error: {str(e)}")
raise
# カテゴリを再度ロックして取得
category_for_update = NewCategory.objects.select_for_update().get(
category_name=category.category_name
)
print(f" Creating entry with following details:")
print(f" - Category: {category_for_update.category_name}")
print(f" - Current category number: {category_for_update.category_number}")
# イベントの日付を取得
entry_date = event.start_datetime.date()
# 既存のエントリーをチェック
existing_entry = Entry.objects.filter(
team=team,
event=event,
date=entry_date,
is_active=True # アクティブなエントリーのみをチェック
).first()
if existing_entry:
print(f" Found existing entry for team {team.team_name} on {entry_date}")
raise ValidationError(
f"Team {team.team_name} already has an entry for event {event.event_name} on {entry_date}"
)
# 現在の番号を取得してインクリメント
current_number = category_for_update.category_number
zekken_number = current_number
# カテゴリ番号をインクリメント
category_for_update.category_number = F('category_number') + 1
category_for_update.save()
# 変更後の値を取得して表示
category_for_update.refresh_from_db()
print(f" Updated category number: {category_for_update.category_number}")
# エントリーの作成
try:
entry = Entry.objects.create(
date=event.start_datetime,
team=team,
category=category,
owner=owner,
event=event,
zekken_number=zekken_number,
is_active=True
)
# バリデーションを実行
entry.full_clean()
# 問題なければ保存
entry.save()
print(f" Created entry:")
print(f" - Team: {team.team_name}")
print(f" - Event: {event.event_name}")
print(f" - Category: {category.category_name}")
print(f" - Zekken Number: {zekken_number}")
return entry
except ValidationError as e:
print(f"Entry validation error: {str(e)}")
raise
except Exception as e:
print(f"Error creating entry: {e}")
print(f"Exception type: {type(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
raise
def split_full_name(self, full_name):
"""
フルネームを姓と名に分割
半角または全角スペースに対応
"""
try:
# 空白文字で分割(半角スペース、全角スペース、タブなど)
parts = full_name.replace(' ', ' ').split()
if len(parts) >= 2:
last_name = parts[0]
first_name = ' '.join(parts[1:]) # 名が複数単語の場合に対応
return last_name, first_name
else:
# 分割できない場合は全体を姓とする
return full_name, ''
except Exception as e:
print(f"Error splitting name '{full_name}': {e}")
return full_name, ''
def convert_japanese_date(self, date_text):
"""
日本式の日付テキストをDateField形式に変換
: '1990年1月1日' -> datetime.date(1990, 1, 1)
"""
try:
if not date_text or date_text.strip() == '':
return None
# 全角数字を半角数字に変換
date_text = date_text.translate(str.maketrans('', '0123456789'))
date_text = date_text.strip()
# 区切り文字の判定と分割
if '' in date_text:
# 年月日形式の場合
date_parts = date_text.replace('', '-').replace('', '-').replace('', '').split('-')
elif '/' in date_text:
# スラッシュ区切りの場合
date_parts = date_text.split('/')
elif '-' in date_text:
date_parts = date_text.split('-')
else:
print(f"Unsupported date format: {date_text}")
return None
# 部分の数を確認
if len(date_parts) != 3:
print(f"Invalid date parts count: {len(date_parts)} in '{date_text}'")
return None
year = int(date_parts[0])
month = int(date_parts[1])
day = int(date_parts[2])
# 簡単な妥当性チェック
if not (1900 <= year <= 2100):
print(f"Invalid year: {year}")
return None
if not (1 <= month <= 12):
print(f"Invalid month: {month}")
return None
if not (1 <= day <= 31): # 月ごとの日数チェックは省略
print(f"Invalid day: {day}")
return None
print(f"Converted from {date_text} to year-{year} / month-{month} / day-{day}")
return date(year, month, day)
except Exception as e:
print(f"Error converting date '{date_text}': {str(e)}")
return None
def create_owner_member( self,team,row ):
"""
オーナーをチームメンバー1として作成
既存のメンバーは更新
"""
try:
owner_name = row.get('owner_name').strip()
# 姓名を分割
last_name, first_name = self.split_full_name(owner_name)
print(f" Split name - Last: {last_name}, First: {first_name}")
# 誕生日の処理
birthday = row.get(f'owner_birthday', '').strip()
birth_date = self.convert_japanese_date(birthday)
print(f" Converted birthday: {birth_date}")
# 性別の処理
sex = row.get(f'owner_sex', '').strip()
is_female = sex in ['女性','','女子','female','girl','lady']
print(f" Sex: {sex}, is_female: {is_female}")
# メンバーを作成
member,created = Member.objects.get_or_create(
team=team,
user=team.owner,
defaults={
'is_temporary': True # 仮登録
}
)
# 既存メンバーの場合は情報を更新
if not created:
member.lastname = last_name
member.firstname = first_name
member.date_of_birth = birth_date
member.female = is_female
member.is_temporary = True
member.save()
print(f" Updated existing member {last_name} {first_name}")
else:
print(f" Created new member {last_name} {first_name}")
return member
except Exception as e:
print(f"Error creating/updating member: {e}")
raise
def create_members(self, team, row):
"""
チームのメンバーを作成
既存のメンバーは更新
"""
try:
created_members = []
# オーナーをメンバーに登録
member = self.create_owner_member(team,row)
created_members.append(member)
# メンバー2から5までを処理
for i in range(2, 6):
member_name = row.get(f'member{i}', '').strip()
if member_name:
print(f"===== Processing member: {member_name} =====")
# 姓名を分割
last_name, first_name = self.split_full_name(member_name)
print(f" Split name - Last: {last_name}, First: {first_name}")
# 誕生日の処理
birthday = row.get(f'birthday{i}', '').strip()
birth_date = self.convert_japanese_date(birthday)
print(f" Converted birthday: {birth_date}")
# 性別の処理
sex = row.get(f'sex{i}', '').strip()
is_female = sex in ['女性','','女子','female','girl','lady']
print(f" Sex: {sex}, is_female: {is_female}")
# メンバー用のユーザーを作成
email = f"dummy_{team.id}_{i}@gifuai.net".lower()
member_user, created = CustomUser.objects.get_or_create(
email=email,
defaults={
'password': make_password('temporary_password'),
'lastname': last_name,
'firstname': first_name,
'date_of_birth': birth_date,
'female':is_female
}
)
# 既存ユーザーの場合も姓名を更新
if not created:
member_user.lastname = last_name
member_user.firstname = first_name
member_user.date_of_birth = birth_date
member_user.female = is_female
member_user.save()
try:
# メンバーを作成
member,created = Member.objects.get_or_create(
team=team,
user=member_user,
defaults={
'is_temporary': True # 仮登録
}
)
# 既存メンバーの場合は情報を更新
if not created:
member.is_temporary = True
member.save()
print(f" Updated existing member {member_user.lastname} {member_user.firstname}")
else:
print(f" Created new member {member_user.lastname} {member_user.firstname}")
created_members.append(member)
print(f" - Birthday: {member_user.date_of_birth}")
print(f" - Sex: {'Female' if member_user.female else 'Male'}")
except Exception as e:
print(f"Error creating/updating member: {e}")
raise
return created_members
except Exception as e:
print(f"Error creating members: {e}")
print(f"Exception type: {type(e)}")
import traceback
print(f"Traceback: {traceback.format_exc()}")
raise
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('upload-csv/', self.upload_csv, name='gifuroge_register_upload_csv'),
]
return custom_urls + urls
def upload_csv(self, request):
print("upload_csv")
if request.method == 'POST':
print("POST")
if 'csv_file' not in request.FILES:
messages.error(request, 'No file was uploaded.')
return redirect('..')
csv_file = request.FILES['csv_file']
print(f"csv_file(1) = {csv_file}")
if not csv_file.name.endswith('.csv'):
messages.error(request, 'File is not CSV type')
return redirect('..')
try:
# BOMを考慮してファイルを読み込む
file_content = csv_file.read()
# BOMがある場合は除去
if file_content.startswith(b'\xef\xbb\xbf'):
file_content = file_content[3:]
# デコード
file_content = file_content.decode('utf-8')
csv_file = StringIO(file_content)
reader = csv.DictReader(csv_file)
print(f"csv_file(2) = {csv_file}")
print(f"reader = {reader}")
with transaction.atomic():
for row in reader:
print(f" row={row}")
# オーナーの姓名を分割
owner_lastname, owner_firstname = self.split_full_name(row['owner_name'])
# パスワードをハッシュ化
hashed_password = make_password(row['password'])
# オーナーの誕生日の処理
owner_birthday = row.get('owner_birthday', '').strip()
owner_birth_date = self.convert_japanese_date(owner_birthday)
print(f" Owner birthday: {owner_birth_date}")
# オーナーの性別の処理
owner_sex = row.get('owner_sex', '').strip()
owner_is_female = owner_sex in ['女性','','女子','female','girl','lady']
print(f" Owner sex: {owner_sex}, is_female: {owner_is_female}")
# ユーザーの取得または作成
user, created = CustomUser.objects.get_or_create(
email=row['email'],
defaults={
'password': hashed_password, # make_password(row['password'])
'lastname': owner_lastname,
'firstname': owner_firstname,
'date_of_birth': owner_birth_date,
'female': owner_is_female
}
)
if not created:
# 既存ユーザーの場合、空のフィールドがあれば更新
should_update = False
update_fields = []
print(f" Checking existing user data for {user.email}:")
print(f" - Current lastname: '{user.lastname}'")
print(f" - Current firstname: '{user.firstname}'")
print(f" - Current birth date: {user.date_of_birth}")
print(f" - Current female: {user.female}")
# 姓が空またはNoneの場合
if not user.lastname or user.lastname.strip() == '':
user.lastname = owner_lastname
should_update = True
update_fields.append('lastname')
print(f" - Updating lastname to: {owner_lastname}")
# 名が空またはNoneの場合
if not user.firstname or user.firstname.strip() == '':
user.firstname = owner_firstname
should_update = True
update_fields.append('firstname')
print(f" - Updating firstname to: {owner_firstname}")
# 生年月日が空またはNoneの場合
if not user.date_of_birth and owner_birth_date:
user.date_of_birth = owner_birth_date
should_update = True
update_fields.append('date_of_birth')
print(f" - Updating birth date to: {owner_birth_date}")
# 性別が空またはNoneの場合
# Booleanフィールドなのでis None で判定
if user.female is None:
user.female = owner_is_female
should_update = True
update_fields.append('female')
print(f" - Updating female to: {owner_is_female}")
# パスワードが'登録済み'でない場合のみ更新
if row['password'] != '登録済み':
user.password = hashed_password
should_update = True
update_fields.append('password')
print(f" - Updating password")
# 変更があった場合のみ保存
if should_update:
try:
# 特定のフィールドのみを更新
user.save(update_fields=update_fields)
print(f" Updated user {user.email} fields: {', '.join(update_fields)}")
except Exception as e:
print(f" Error updating user {user.email}: {str(e)}")
raise
else:
print(f" No updates needed for user {user.email}")
print(f" user created...")
print(f" Owner member created: {user.lastname} {user.firstname}")
print(f" - Birthday: {user.date_of_birth}")
print(f" - Sex: {'Female' if user.female else 'Male'}")
# 適切なカテゴリを見つける
category = self.find_matching_category(
time=int(row['time']),
department=row['department']
)
if not category:
raise ValueError(
f"No matching category found for time={row['time']} minutes "
f"and department={row['department']}"
)
print(f" Using category: {category.category_name}")
# Teamの作成既存のチームがある場合は取得
team, created = Team.objects.get_or_create(
team_name=row['team_name'],
defaults={
'owner': user,
'category': category
}
)
# 既存のチームの場合でもカテゴリを更新
if not created:
team.category = category
team.save()
print(" team created/updated...")
self.create_members(team, row)
# イベントの検索
try:
event_code = row['event_code']
event = NewEvent2.objects.get(event_name=event_code)
print(f" Found event: {event.event_name}")
except NewEvent2.DoesNotExist:
raise ValueError(f"Event with code {event_code} does not exist")
try:
# エントリーの作成
entry = self.create_entry_with_number(
team=team,
category=category,
owner=user,
event=event,
)
print(" entry created...")
except ValidationError as e:
messages.error(request, str(e))
return redirect('..')
gifuroge_register = GifurogeRegister.objects.create(
event_code=row['event_code'],
time=int(row['time']),
owner_name_kana=row['owner_name_kana'],
owner_name=row['owner_name'],
owner_birthday=self.convert_japanese_date(row['owner_birthday']),
owner_sex=row['owner_sex'],
email=row['email'],
password=row['password'],
team_name=row['team_name'],
department=row['department'],
members_count=int(row['members_count']),
member2=row.get('member2', '') or None,
birthday2=self.convert_japanese_date(row.get('birthday2', '') ),
sex2=row.get('sex2', '') or None,
member3=row.get('member3', '') or None,
birthday3=self.convert_japanese_date(row.get('birthday3', '') ),
sex3=row.get('sex3', '') or None,
member4=row.get('member4', '') or None,
birthday4=self.convert_japanese_date(row.get('birthday4', '') ),
sex4=row.get('sex4', '') or None,
member5=row.get('member5', '') or None,
birthday5=self.convert_japanese_date(row.get('birthday5', '') ),
sex5=row.get('sex5', '') or None
)
print(f" saved gifuroge_register...")
except UnicodeDecodeError:
messages.error(request, 'File encoding error. Please ensure the file is UTF-8 encoded.')
return redirect('..')
except Exception as e:
print(f"Error processing row: {e}")
raise
messages.success(request, 'CSV file uploaded successfully')
return redirect('..')
return render(request, 'admin/rog/gifurogeregister/upload-csv.html')
class RogAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
list_display=['title', 'venue', 'at_date',]
class ShopAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
list_display=['name',]
class EventRouteAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
list_display=['name',]
class ShopRouteAdmin(LeafletAdminListMixin, LeafletGeoAdminMixin, admin.ModelAdmin):
list_display=['name',]
class loadUserForm(forms.Form):
server_url = forms.CharField(label="Load Data from *" ,initial='https://natnats.mobilous.com/get_team_list', widget=forms.Textarea(attrs={"rows":2, "cols":95}))
class UserAdminConfig(UserAdmin):
search_fields = ('email', 'group', 'zekken_number', 'event_code', 'team_name', 'is_rogaining')
list_filter = ('email', 'group', 'is_rogaining')
ordering = ('email',)
list_display = ('email', 'group','zekken_number', 'event_code', 'team_name', 'is_active', 'is_staff', 'is_rogaining')
def get_urls(self):
urls = super().get_urls()
new_url = [path('load-users/', self.loadUsers),]
return new_url + urls
def loadUsers(self, request):
if request.method == "POST":
frm = loadUserForm(request.POST)
if frm.is_valid():
print(frm.cleaned_data['server_url'])
#load json from server
url = frm.cleaned_data['server_url']
response = requests.get(url)
data = response.json()
print("-------Event code--------")
print(data)
print("-------Event code--------")
for i in data:
_exist = CustomUser.objects.filter(email=i["zekken_number"]).delete()
other_fields.setDefaut('zekken_number',i['zekken_number'])
other_fields.setdefault('is_staff', True)
other_fields.setdefault('is_superuser', False)
other_fields.setdefault('is_active', True)
other_fields.setdefault('event_code', i['event_code'])
other_fields.setdefault('team_name', i['team_name'])
other_fields.setdefault('group', '大垣-初心者')
usr = CustomUser.objects.create_user(
email=i["zekken_number"],
password=i['password'],
**other_fields
)
form = loadUserForm()
data = {'form': form}
return render(request, 'admin/load_users.html', data)
"""
fieldsets = (
(None, {'fields':('email', 'group', 'zekken_number', 'event_code', 'team_name',)}),
('Permissions', {'fields':('is_staff', 'is_active', 'is_rogaining')}),
)
add_fieldsets = (
(None, {'classes':('wide',), 'fields':('email', 'group','zekken_number', 'event_code', 'team_name', 'password1', 'password2')}),
)
"""
# readonly_fieldsを明示的に設定
readonly_fields = ('date_joined',) # 変更不可のフィールドのみを指定=>Personal Infoも編集可能にする。
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {
'fields': ('firstname', 'lastname', 'date_of_birth', 'female'),
'classes': ('wide',) # フィールドの表示を広げる
}),
(_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_rogaining','user_permissions')}),
(_('Rogaining info'), {
'fields': ('zekken_number', 'event_code', 'team_name', 'group'),
'classes': ('wide',)
}),
(_('Important dates'), {
'fields': ('date_joined','last_login'),
'classes': ('wide',)
}), # 読み取り専用
)
add_fieldsets = (
(None, {
'classes': ('wide',),
#'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active', 'is_rogaining')}
'fields': ('email', 'password1', 'password2', 'lastname','firstname', 'date_of_birth', 'female','is_staff', 'is_active', 'is_rogaining')}
),
)
search_fields = ('email', 'firstname', 'lastname', 'zekken_number', 'team_name')
ordering = ('email',)
class JpnSubPerfAdmin(LeafletGeoAdmin):
search_fields = ('adm0_ja', 'adm1_ja', 'adm2_ja', 'name_modified', 'area_name',)
list_filter = ('adm0_ja', 'adm0_ja', 'name_modified',)
ordering = ('adm0_ja',)
list_display = ('adm0_ja','adm1_ja','adm2_ja' ,'name_modified', 'area_name',)
class LocationAdmin(LeafletGeoAdmin):
search_fields = ('location_id', 'cp', 'location_name', 'category', 'event_name','group',)
list_filter = ('event_name', 'group',)
ordering = ('location_id', 'cp',)
list_display = ('location_id','sub_loc_id', 'cp', 'location_name', 'photos', 'category', 'group', 'event_name', 'event_active', 'auto_checkin', 'checkin_radius', 'checkin_point', 'buy_point',)
def tranfer_to_location(modeladmin, request, queryset):
tmp_locs = templocation.objects.all();
for l in tmp_locs :
found = Location.objects.filter(location_id = l.location_id).exists()
if found:
Location.objects.filter(location_id = l.location_id).update(
sub_loc_id = l.sub_loc_id,
cp = l.cp,
location_name = l.location_name,
category = l.category,
subcategory = l.subcategory,
zip = l.zip,
address = l.address,
prefecture = l.prefecture,
area = l.area,
city = l.city,
latitude = l.latitude,
longitude = l.longitude,
photos = l.photos,
videos = l.videos,
webcontents = l.webcontents,
status = l.status,
portal = l.portal,
group = l.group,
phone = l.phone,
fax = l.fax,
email = l.email,
facility = l.facility,
remark = l.remark,
tags = l.tags,
hidden_location = l.hidden_location,
auto_checkin = l.auto_checkin,
checkin_radius = l.checkin_radius,
checkin_point = l.checkin_point,
buy_point = l.buy_point,
evaluation_value = l.evaluation_value,
shop_closed = l.shop_closed,
shop_shutdown = l.shop_shutdown,
opening_hours_mon = l.opening_hours_mon,
opening_hours_tue = l.opening_hours_tue,
opening_hours_wed = l.opening_hours_wed,
opening_hours_thu = l.opening_hours_thu,
opening_hours_fri = l.opening_hours_fri,
opening_hours_sat = l.opening_hours_sat,
opening_hours_sun = l.opening_hours_sun,
geom=l.geom
)
else:
loc = Location(
location_id=l.location_id,
sub_loc_id = l.sub_loc_id,
cp = l.cp,
location_name = l.location_name,
category = l.category,
subcategory = l.subcategory,
zip = l.zip,
address = l.address,
prefecture = l.prefecture,
area = l.area,
city = l.city,
latitude = l.latitude,
longitude = l.longitude,
photos = l.photos,
videos = l.videos,
webcontents = l.webcontents,
status = l.status,
portal = l.portal,
group = l.group,
phone = l.phone,
fax = l.fax,
email = l.email,
facility = l.facility,
remark = l.remark,
tags = l.tags,
hidden_location = l.hidden_location,
auto_checkin = l.auto_checkin,
checkin_radius = l.checkin_radius,
checkin_point = l.checkin_point,
buy_point = l.buy_point,
evaluation_value = l.evaluation_value,
shop_closed = l.shop_closed,
shop_shutdown = l.shop_shutdown,
opening_hours_mon = l.opening_hours_mon,
opening_hours_tue = l.opening_hours_tue,
opening_hours_wed = l.opening_hours_wed,
opening_hours_thu = l.opening_hours_thu,
opening_hours_fri = l.opening_hours_fri,
opening_hours_sat = l.opening_hours_sat,
opening_hours_sun = l.opening_hours_sun,
geom=l.geom
)
loc.save()
l.delete()
2025-01-22 18:29:54 +09:00
return True
2025-01-22 18:31:49 +09:00
#tranfer_to_location.short_description = "Transfer all locations in temp table to location table"
2024-10-27 18:22:01 +00:00
class TempLocationAdmin(LeafletGeoAdmin):
search_fields = ('location_id', 'cp', 'location_name', 'category', 'event_name',)
list_filter = ('category', 'event_name',)
ordering = ('location_id', 'cp',)
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(NewEvent2)
class NewEvent2Admin(admin.ModelAdmin):
list_display = ['event_name', 'start_datetime', 'end_datetime', 'csv_upload_button']
def get_urls(self):
urls = super().get_urls()
my_urls = [
path('csv-upload/', self.admin_site.admin_view(self.csv_upload_view), name='newevent2_csv_upload'),
]
return my_urls + urls
def csv_upload_view(self, request):
if request.method == 'POST':
form = CSVUploadForm(request.POST, request.FILES)
if form.is_valid():
csv_file = request.FILES['csv_file']
event = form.cleaned_data['event']
process_csv_upload(csv_file, event)
self.message_user(request, "CSV file has been processed successfully.")
return HttpResponseRedirect("../")
else:
form = CSVUploadForm()
return render(request, 'admin/csv_upload.html', {'form': form})
def csv_upload_button(self, obj):
url = reverse('admin:newevent2_csv_upload')
return format_html('<a class="button" href="{}">CSVアップロード</a>', url)
csv_upload_button.short_description = 'CSV Upload'
def changelist_view(self, request, extra_context=None):
extra_context = extra_context or {}
extra_context['csv_upload_url'] = reverse('admin:newevent2_csv_upload')
return super().changelist_view(request, extra_context=extra_context)
@admin.register(Team)
class TeamAdmin(admin.ModelAdmin):
list_display = ['team_name', 'owner']
search_fields = ['team_name', 'owner__email']
@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']
2025-01-22 18:18:03 +09:00
#@admin.register(Entry)
#class EntryAdmin(admin.ModelAdmin):
# list_display = ['team', 'event', 'category', 'date']
# list_filter = ['event', 'category']
# search_fields = ['team__team_name', 'event__event_name']
2024-10-27 18:22:01 +00:00
@admin.register(Member)
class MemberAdmin(admin.ModelAdmin):
list_display = ['team', 'user']
search_fields = ['team__team_name', 'user__email']
@admin.register(TempUser)
class TempUserAdmin(admin.ModelAdmin):
list_display = ['email', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'created_at', 'expires_at']
list_filter = ['is_rogaining', 'group']
search_fields = ['email', 'zekken_number', 'team_name']
# CustomUserAdmin の修正(既存のものを更新)
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CustomUser
fields = '__all__'
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = ('email', 'lastname', 'firstname', 'date_of_birth', 'female')
2025-01-22 08:19:49 +00:00
@admin.register(CustomUser)
2024-10-27 18:22:01 +00:00
class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
2025-01-22 08:19:49 +00:00
#model = CustomUser
2024-10-27 18:22:01 +00:00
list_display = ('email', 'is_staff', 'is_active', 'is_rogaining', 'zekken_number', 'event_code', 'team_name', 'group', 'firstname', 'lastname')
2025-01-22 17:14:56 +09:00
search_fields = ('egit mail', 'firstname', 'lastname', 'zekken_number')
2024-10-27 18:22:01 +00:00
list_filter = ('is_staff', 'is_active', 'is_rogaining', 'group')
2024-12-19 12:57:57 +09:00
ordering = ('email',)
2024-10-27 18:22:01 +00:00
# readonly_fieldsを明示的に設定
readonly_fields = ('date_joined',) # 変更不可のフィールドのみを指定=>Personal Infoも編集可能にする。
fieldsets = (
(None, {'fields': ('email', 'password')}),
(_('Personal info'), {
'fields': ('firstname', 'lastname', 'date_of_birth', 'female'),
'classes': ('wide',) # フィールドの表示を広げる
}),
(_('Permissions'), {'fields': ('is_staff', 'is_active', 'is_rogaining','user_permissions')}),
(_('Rogaining info'), {
'fields': ('zekken_number', 'event_code', 'team_name', 'group'),
'classes': ('wide',)
}),
(_('Important dates'), {
'fields': ('date_joined','last_login'),
'classes': ('wide',)
}), # 読み取り専用
)
add_fieldsets = (
(None, {
'classes': ('wide',),
#'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active', 'is_rogaining')}
'fields': ('email', 'password1', 'password2', 'lastname','firstname', 'date_of_birth', 'female','is_staff', 'is_active', 'is_rogaining')}
),
)
search_fields = ('email', 'firstname', 'lastname', 'zekken_number', 'team_name')
ordering = ('email',)
2025-01-22 08:19:49 +00:00
def get_readonly_fields_old(self, request, obj=None):
2024-10-27 18:22:01 +00:00
# スーパーユーザーの場合は読み取り専用フィールドを最小限に
if request.user.is_superuser:
return self.readonly_fields
# 通常のスタッフユーザーの場合は追加の制限を設定可能
return self.readonly_fields + ('is_staff', 'is_superuser')
2025-01-22 08:19:49 +00:00
def get_readonly_fields(self, request, obj=None):
if request.user.is_superuser:
return ('date_joined', 'last_login')
return ('date_joined', 'last_login', 'is_staff', 'is_superuser')