2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2026-02-08 13:18:15 +00:00

more progress to better serializer

This commit is contained in:
2025-11-22 11:38:00 +02:00
parent f52eab842f
commit 7889162420
2 changed files with 61 additions and 57 deletions

View File

@@ -327,9 +327,6 @@ def shared_use_machine(request):
print(f" - shared use cookie exists, but has wrong value: '{cookie_txt}' not '{PUBLIC_LAPTOP_COOKIE_TEXT}'")
return True
def get_cookie(request):
"""The initial idea of having a default turned out to be a bad idea as people just ignore the field.
If the default value is blank, then the form validation code makes the user type something in.
@@ -539,6 +536,18 @@ class WriteAndCommitError(Exception):
def __str__(self):
return f"WriteAndCommitError: {self.message}"
# Custom JSON Encoder to handle non-serializable types
class CustomJSONEncoder(json.JSONEncoder):
def default(self, obj):
# Convert datetime objects to ISO 8601 string format
if isinstance(obj, datetime):
return obj.isoformat()
# Convert Decimal objects to string
if isinstance(obj, Decimal):
# Use str() for perfect precision, or float() for numerical representation
return str(obj)
# Let the base class handle other types
return json.JSONEncoder.default(self, obj)
"""The following is a Bard converted version of Radosts's MIT copyrighted Javascript on 2023-10-27
with hand-editing.

View File

@@ -1,20 +1,24 @@
import json
import re
from datetime import datetime
from decimal import Decimal
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.serializers import serialize
from django.db.models import Q
from django.forms.models import model_to_dict
from django.shortcuts import redirect, render
from django.views.generic.list import ListView
from django.contrib.auth.models import User
import troggle.settings as settings
from troggle.core.models.logbooks import QM, LogbookEntry, PersonLogEntry, writelogbook
from troggle.core.models.survex import SurvexBlock, SurvexFile
from troggle.core.models.troggle import Expedition, Person
from troggle.core.models.wallets import Wallet
from troggle.core.utils import TROG, current_expo, add_commit, git_commit, git_add, get_editor
from troggle.core.utils import TROG, current_expo, add_commit, git_commit, git_add, get_editor, ensure_dir_exists, CustomJSONEncoder
from troggle.parsers.imports import import_logbook
"""These views are for logbook items when they appear in an 'expedition' page
@@ -399,6 +403,8 @@ def write_entries(entries, year, editor):
"""
def write_json_file():
# uses filepath, jsondict from context
try:
with open(filepath, 'w', encoding='utf-8') as json_f:
json.dump(jsondict, json_f, indent=1)
@@ -410,78 +416,67 @@ def write_entries(entries, year, editor):
print(f"CANNOT write this file {filepath}. Exception dumping json. Ask a nerd to fix this: {e}")
raise e
def serialize_logentry():
# REPLACE this with hand-built serializer which includes .author, .who which were added to the entries but re not in the model Class directly
# see below for Gemini code to do that. Going to bed now.
jsondict = serialize("json", [le], fields=('slug', 'date', 'expedition', 'title', 'cave', 'place', 'other_people', 'time_underground', 'text'))
return jsondict
dirpath = settings.EXPOWEB / "years" / year / LOGBOOK_ENTRIES
dirpath.mkdir(parents=True, exist_ok=True)
for le in entries:
filename = f"{le.slug}-{le.pk:03}.json"
filepath = dirpath / filename
# description = f" {le.slug} :: {le.date} - {le.title}"
ensure_dir_exists(filepath)
# REPLACE this with hand-built serializer which includes .author, .who which were added to the entries but re not in the model Class directly
# see below for Gemini code to do that. Going to bed now.
jsondict = serialize("json", [le], fields=('slug', 'date', 'expedition', 'title', 'cave', 'place', 'other_people', 'time_underground', 'text'))
jsondict = serialize_logentry()
write_json_file()
git_add(filename, dirpath)
commit_msg = f"Exporting logbook entries as individual files"
commit_msg = f"Exporting {len(entries)} logbook entries as individual files."
git_commit(dirpath, commit_msg, editor)
return True
# Gemini has the answer, get what I need from this:
# from django.http import JsonResponse, HttpResponse
# # from .models import LogbookEntry, PersonLogEntry, Person # Import your models
# from django.forms.models import model_to_dict
# from datetime import datetime
# import json
# from decimal import Decimal
# # Re-using the custom encoder from the previous suggestion for robust date/decimal handling
# class CustomJSONEncoder(json.JSONEncoder):
# def default(self, obj):
# if isinstance(obj, datetime):
# return obj.isoformat()
# if isinstance(obj, Decimal):
# return str(obj)
# return json.JSONEncoder.default(self, obj)
# def export_entry_with_author_details(request, entry_id):
# try:
# # 1. Get the LogbookEntry instance
# entry = LogbookEntry.objects.get(pk=entry_id)
# # 2. Get the related PersonLogEntry and Person (Author)
# # Use .select_related() for efficiency
# author_link = PersonLogEntry.objects.select_related('person').get(
# entry=entry,
# is_author=True # Adjust filter based on your logic
# )
# author = author_link.person
# except (LogbookEntry.DoesNotExist, PersonLogEntry.DoesNotExist):
# return HttpResponse(f'Entry or Author not found for ID {entry_id}', status=404)
# # 3. Manually create the nested dictionary structure
# # Use model_to_dict for easy extraction of the simple fields
# # Author data (specify fields you want to expose)
# author_data = model_to_dict(author, fields=['id', 'first_name', 'last_name', 'email'])
# # Entry data (specify fields you want to expose)
# entry_data = model_to_dict(entry, fields=['id', 'title', 'content', 'date_created'])
# # Nest the author data inside the entry data
# entry_data['author'] = author_data
# # Add data from the intermediate model if needed (e.g., the date the person was added)
# entry_data['author_assignment_date'] = author_link.date_assigned.isoformat()
# # 4. Return the custom dictionary using JsonResponse
# return JsonResponse(
# entry_data,
# encoder=CustomJSONEncoder,
# safe=False # Set to True if entry_data was a list/QuerySet
# )
def export_entry_with_author_details(request, entry_id):
try:
# 1. Get the LogbookEntry instance
entry = LogbookEntry.objects.get(pk=entry_id)
# 2. Get the related PersonLogEntry and Person (Author)
# Use .select_related() for efficiency
author_link = PersonLogEntry.objects.select_related('person').get(
entry=entry,
is_author=True # Adjust filter based on your logic
)
author = author_link.person
except (LogbookEntry.DoesNotExist, PersonLogEntry.DoesNotExist):
return HttpResponse(f'Entry or Author not found for ID {entry_id}', status=404)
# 3. Manually create the nested dictionary structure
# Use model_to_dict for easy extraction of the simple fields
# Author data (specify fields you want to expose)
author_data = model_to_dict(author, fields=['id', 'first_name', 'last_name', 'email'])
# Entry data (specify fields you want to expose)
entry_data = model_to_dict(entry, fields=['id', 'title', 'content', 'date_created'])
# Nest the author data inside the entry data
entry_data['author'] = author_data
# Add data from the intermediate model if needed (e.g., the date the person was added)
entry_data['author_assignment_date'] = author_link.date_assigned.isoformat()
# 4. Return the custom dictionary using JsonResponse
return JsonResponse(
entry_data,
encoder=CustomJSONEncoder,
safe=False # Set to True if entry_data was a list/QuerySet
)