Fix API and admin for location2025
This commit is contained in:
35
rog/admin.py
35
rog/admin.py
@ -1039,16 +1039,21 @@ class WaypointAdmin(admin.ModelAdmin):
|
||||
|
||||
@admin.register(Location2025)
|
||||
class Location2025Admin(LeafletGeoAdmin):
|
||||
"""Location2025の管理画面"""
|
||||
"""Location2025の管理画面(全フィールド対応)"""
|
||||
list_display = [
|
||||
'cp_number', 'cp_name', 'event', 'total_point', 'is_active',
|
||||
'cp_number', 'cp_name', 'event', 'sub_loc_id', 'subcategory',
|
||||
'total_point', 'has_photos', 'has_videos', 'is_active',
|
||||
'csv_upload_date', 'created_at'
|
||||
]
|
||||
list_filter = [
|
||||
'event', 'is_active', 'shop_closed', 'shop_shutdown',
|
||||
'subcategory', 'hidden_location',
|
||||
'csv_upload_date', 'created_at'
|
||||
]
|
||||
search_fields = ['cp_name', 'address', 'description']
|
||||
search_fields = [
|
||||
'cp_name', 'address', 'description', 'remark', 'tags',
|
||||
'sub_loc_id', 'subcategory', 'evaluation_value'
|
||||
]
|
||||
readonly_fields = [
|
||||
'csv_source_file', 'csv_upload_date', 'csv_upload_user',
|
||||
'created_at', 'updated_at', 'created_by', 'updated_by'
|
||||
@ -1056,7 +1061,7 @@ class Location2025Admin(LeafletGeoAdmin):
|
||||
|
||||
fieldsets = (
|
||||
('基本情報', {
|
||||
'fields': ('cp_number', 'event', 'cp_name', 'is_active', 'sort_order')
|
||||
'fields': ('cp_number', 'event', 'cp_name', 'sub_loc_id', 'subcategory', 'is_active', 'sort_order')
|
||||
}),
|
||||
('位置情報', {
|
||||
'fields': ('latitude', 'longitude', 'location', 'address')
|
||||
@ -1071,7 +1076,15 @@ class Location2025Admin(LeafletGeoAdmin):
|
||||
'fields': ('shop_closed', 'shop_shutdown', 'opening_hours')
|
||||
}),
|
||||
('詳細情報', {
|
||||
'fields': ('phone', 'website', 'description')
|
||||
'fields': ('phone', 'website', 'description', 'remark')
|
||||
}),
|
||||
('メディア・タグ情報', {
|
||||
'fields': ('photos', 'videos', 'tags', 'evaluation_value'),
|
||||
'classes': ('wide',)
|
||||
}),
|
||||
('高度設定', {
|
||||
'fields': ('hidden_location',),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('CSV情報', {
|
||||
'fields': ('csv_source_file', 'csv_upload_date', 'csv_upload_user'),
|
||||
@ -1083,6 +1096,18 @@ class Location2025Admin(LeafletGeoAdmin):
|
||||
}),
|
||||
)
|
||||
|
||||
def has_photos(self, obj):
|
||||
"""写真データ有無の表示"""
|
||||
return bool(obj.photos and obj.photos.strip())
|
||||
has_photos.boolean = True
|
||||
has_photos.short_description = '写真'
|
||||
|
||||
def has_videos(self, obj):
|
||||
"""動画データ有無の表示"""
|
||||
return bool(obj.videos and obj.videos.strip())
|
||||
has_videos.boolean = True
|
||||
has_videos.short_description = '動画'
|
||||
|
||||
# CSV一括アップロード機能
|
||||
change_list_template = 'admin/location2025/change_list.html'
|
||||
|
||||
|
||||
@ -36,17 +36,85 @@ class LocationCatSerializer(serializers.ModelSerializer):
|
||||
fields=['category',]
|
||||
|
||||
|
||||
class LocationSerializer(GeoFeatureModelSerializer):
|
||||
class LocationSerializer(serializers.ModelSerializer):
|
||||
# evaluation_valueに基づくインタラクション情報を追加
|
||||
interaction_type = serializers.SerializerMethodField()
|
||||
requires_photo = serializers.SerializerMethodField()
|
||||
requires_qr_code = serializers.SerializerMethodField()
|
||||
interaction_instructions = serializers.SerializerMethodField()
|
||||
|
||||
# 追加フィールドのカスタムシリアライズ
|
||||
has_photos = serializers.SerializerMethodField()
|
||||
has_videos = serializers.SerializerMethodField()
|
||||
photos_list = serializers.SerializerMethodField()
|
||||
videos_list = serializers.SerializerMethodField()
|
||||
tags_list = serializers.SerializerMethodField()
|
||||
|
||||
# 位置情報の緯度経度
|
||||
latitude_float = serializers.SerializerMethodField()
|
||||
longitude_float = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model=Location2025
|
||||
geo_field='geom'
|
||||
fields="__all__"
|
||||
fields=[
|
||||
# 基本フィールド
|
||||
'id', 'cp_number', 'event', 'cp_name', 'sub_loc_id', 'subcategory',
|
||||
'latitude', 'longitude', 'location', 'address',
|
||||
'cp_point', 'photo_point', 'buy_point',
|
||||
'checkin_radius', 'auto_checkin',
|
||||
'shop_closed', 'shop_shutdown', 'opening_hours',
|
||||
'phone', 'website', 'description', 'remark',
|
||||
# 追加フィールド
|
||||
'photos', 'videos', 'tags', 'evaluation_value', 'hidden_location',
|
||||
# 管理フィールド
|
||||
'is_active', 'sort_order', 'csv_source_file', 'csv_upload_date',
|
||||
'created_at', 'updated_at', 'created_by', 'updated_by',
|
||||
# カスタムフィールド
|
||||
'interaction_type', 'requires_photo', 'requires_qr_code', 'interaction_instructions',
|
||||
'has_photos', 'has_videos', 'photos_list', 'videos_list', 'tags_list',
|
||||
'latitude_float', 'longitude_float'
|
||||
]
|
||||
|
||||
def get_latitude_float(self, obj):
|
||||
"""位置情報から緯度を取得"""
|
||||
if obj.location:
|
||||
return obj.location.y
|
||||
return obj.latitude
|
||||
|
||||
def get_longitude_float(self, obj):
|
||||
"""位置情報から経度を取得"""
|
||||
if obj.location:
|
||||
return obj.location.x
|
||||
return obj.longitude
|
||||
|
||||
def get_has_photos(self, obj):
|
||||
"""写真データの有無を返す"""
|
||||
return bool(obj.photos and obj.photos.strip())
|
||||
|
||||
def get_has_videos(self, obj):
|
||||
"""動画データの有無を返す"""
|
||||
return bool(obj.videos and obj.videos.strip())
|
||||
|
||||
def get_photos_list(self, obj):
|
||||
"""写真ファイル名をリストで返す"""
|
||||
if not obj.photos or not obj.photos.strip():
|
||||
return []
|
||||
# カンマ区切りで分割してリストとして返す
|
||||
return [photo.strip() for photo in obj.photos.split(',') if photo.strip()]
|
||||
|
||||
def get_videos_list(self, obj):
|
||||
"""動画ファイル名をリストで返す"""
|
||||
if not obj.videos or not obj.videos.strip():
|
||||
return []
|
||||
# カンマ区切りで分割してリストとして返す
|
||||
return [video.strip() for video in obj.videos.split(',') if video.strip()]
|
||||
|
||||
def get_tags_list(self, obj):
|
||||
"""タグをリストで返す"""
|
||||
if not obj.tags or not obj.tags.strip():
|
||||
return []
|
||||
# カンマ区切りで分割してリストとして返す
|
||||
return [tag.strip() for tag in obj.tags.split(',') if tag.strip()]
|
||||
|
||||
def get_interaction_type(self, obj):
|
||||
"""evaluation_valueに基づくインタラクションタイプを返す"""
|
||||
|
||||
44
rog/views.py
44
rog/views.py
@ -24,7 +24,7 @@ import uuid
|
||||
from rest_framework.exceptions import ValidationError as DRFValidationError
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import F,Sum
|
||||
from django.db.models import F,Sum,Q
|
||||
from rest_framework import viewsets, permissions, status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
@ -239,17 +239,49 @@ class NewEvent2Admin(admin.ModelAdmin):
|
||||
class LocationViewSet(viewsets.ModelViewSet):
|
||||
queryset=Location2025.objects.all()
|
||||
serializer_class=LocationSerializer
|
||||
filter_fields=["prefecture", "location_name"]
|
||||
filter_fields=[
|
||||
"event", "cp_name", "subcategory", "sub_loc_id",
|
||||
"is_active", "hidden_location", "evaluation_value"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = Location2025.objects.all()
|
||||
|
||||
# リクエストパラメータの確認
|
||||
group_filter = self.request.query_params.get('group__contains')
|
||||
event_filter = self.request.query_params.get('event')
|
||||
subcategory_filter = self.request.query_params.get('subcategory')
|
||||
has_photos_filter = self.request.query_params.get('has_photos')
|
||||
has_videos_filter = self.request.query_params.get('has_videos')
|
||||
tags_filter = self.request.query_params.get('tags__contains')
|
||||
evaluation_filter = self.request.query_params.get('evaluation_value')
|
||||
hidden_filter = self.request.query_params.get('hidden_location')
|
||||
|
||||
if group_filter:
|
||||
# フィルタの適用
|
||||
queryset = queryset.filter(group__contains=group_filter)
|
||||
if event_filter:
|
||||
queryset = queryset.filter(event_id=event_filter)
|
||||
|
||||
if subcategory_filter:
|
||||
queryset = queryset.filter(subcategory__icontains=subcategory_filter)
|
||||
|
||||
if has_photos_filter == 'true':
|
||||
queryset = queryset.exclude(photos__isnull=True).exclude(photos='')
|
||||
elif has_photos_filter == 'false':
|
||||
queryset = queryset.filter(Q(photos__isnull=True) | Q(photos=''))
|
||||
|
||||
if has_videos_filter == 'true':
|
||||
queryset = queryset.exclude(videos__isnull=True).exclude(videos='')
|
||||
elif has_videos_filter == 'false':
|
||||
queryset = queryset.filter(Q(videos__isnull=True) | Q(videos=''))
|
||||
|
||||
if tags_filter:
|
||||
queryset = queryset.filter(tags__icontains=tags_filter)
|
||||
|
||||
if evaluation_filter:
|
||||
queryset = queryset.filter(evaluation_value=evaluation_filter)
|
||||
|
||||
if hidden_filter == 'true':
|
||||
queryset = queryset.filter(hidden_location=True)
|
||||
elif hidden_filter == 'false':
|
||||
queryset = queryset.filter(hidden_location=False)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
Reference in New Issue
Block a user