diff --git a/core/views/logbooks.py b/core/views/logbooks.py index c042d6a..716e17c 100644 --- a/core/views/logbooks.py +++ b/core/views/logbooks.py @@ -14,7 +14,7 @@ from troggle.core.models.logbooks import QM, LogbookEntry, PersonLogEntry, write 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 +from troggle.core.utils import TROG, current_expo, add_commit, git_commit, git_add, get_editor from troggle.parsers.imports import import_logbook """These views are for logbook items when they appear in an 'expedition' page @@ -266,7 +266,26 @@ def logentrydelete(request, year): return redirect(f"/logreport/{year}") +def get_entries(year): + expo = Expedition.objects.get(year=int(year)) + entries = expo.logbookentry_set.all() # lazy list + dateditems = list(entries) # evaluates the Django query and hits db + try: + for entry in dateditems: + people = PersonLogEntry.objects.filter(logbook_entry=entry) + entry.who = [] + for p in people: + if p.is_logbook_entry_author: + entry.author = p + else: + entry.who.append(p) + except Exception as e: + msg = f' Logbook report for year:"{year}" not implemented yet\n{e}\n {context}' + print(msg) + return render(request, "errors/generic.html", {"message": msg}) + return dateditems + def logreport(request, year=1999): """ Remember that 'personexpedition__expedition' is interpreted by Django to mean the @@ -278,15 +297,10 @@ def logreport(request, year=1999): # print(f"logreport(): begun") expeditions = Expedition.objects.all() # top menu only, evaluated only when template renders - dates = None - dateditems = None - logged_in = False - - + logged_in = False if request.user.is_superuser: # expoadmin is both .is_staff and ._is_superuser logged_in = True - try: expo = Expedition.objects.get(year=int(year)) except: @@ -295,39 +309,23 @@ def logreport(request, year=1999): ) return render(request, "errors/generic.html", {"message": message}) - entries = expo.logbookentry_set.all() # lazy list - dateditems = list(entries) # evaluates the Django query and hits db + dateditems = get_entries(year) dates = sorted(set([item.date for item in dateditems])) - - try: - for entry in dateditems: - - people = PersonLogEntry.objects.filter(logbook_entry=entry) - entry.who = [] - for p in people: - if p.is_logbook_entry_author: - entry.author = p - else: - entry.who.append(p) - - - # print(f"logreport(): trying..") - context = { - "year": year, - "expedition": expo, - "expeditions": expeditions, - "settings": settings, - "dateditems": dateditems, - "dates": dates, - "logged_in": logged_in, - } - # print(f"logreport(): rendering..") - return render(request, "logreport.html", context) + + # print(f"logreport(): trying..") + context = { + "year": year, + "expedition": expo, + "expeditions": expeditions, + "settings": settings, + "dateditems": dateditems, + "dates": dates, + "logged_in": logged_in, + } + # print(f"logreport(): rendering..") + return render(request, "logreport.html", context) + - except Exception as e: - msg = f' Logbook report for year:"{year}" not implemented yet\n{e}\n {context}' - print(msg) - return render(request, "errors/generic.html", {"message": msg}) def logbookentry(request, date, slug): """Displays a single logbook entry @@ -382,29 +380,37 @@ def get_logbook_entries(request, expeditionslug): def logbook_entries_export(request, year): exp = Expedition.objects.get(year=year) - entries = exp.logbookentry_set.all() - for e in entries[:3]: - print(f"{e}") + entries = get_entries(year) + # for e in entries: + # print(f"{e.pk:03} {e}") - write_entries(entries[:3], year) + editor = get_editor(request) + write_entries(entries, year, editor) return redirect(f"/logreport/{year}") -def write_entries(entries, year, git_string=None): - if not git_string: - git_string = f"troggle " +def write_entries(entries, year, editor): - dirpath = settings.EXPOWEB / "years" / year - - for le in entries[:4]: - jsondict = { "logbook_entry": le } - #print(jsondict) - - jsondict = serialize("json", [le], fields=('date', 'expedition', 'title', 'cave', 'place', 'other_people', 'date_field', 'text', 'slug', 'time_underground')) - print(jsondict) - filepath = dirpath / le.slug + dirpath = settings.EXPOWEB / "years" / year / "log_entries" + try: + dirpath.mkdir(parents=True, exist_ok=True) + except PermissionError as e: + raise PermissionError( + f"CANNOT make the directory.\nPERMISSIONS incorrectly set on server for this file {filepath}. Ask a nerd to fix this: {e}" + ) + except Exception as e: + raise OSError( + f"CANNOT make the directory for {filepath}. Ask a nerd to fix this: {e}" + ) + + for le in entries: + # 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')) + + filename = f"{le.slug}-{le.pk:03}.json" + filepath = dirpath / filename description = f" {le.slug} :: {le.date} - {le.title}" - print(filepath, description) try: with open(filepath, 'w', encoding='utf-8') as json_f: json.dump(jsondict, json_f, indent=1) @@ -414,8 +420,67 @@ def write_entries(entries, year, git_string=None): ) except Exception as e: print(f"CANNOT write this file {filepath}. Exception dumping json. Ask a nerd to fix this: {e}") - raise e + raise e + + git_add(filename, dirpath) commit_msg = f"Exporting logbook entries as individual files" - git_commit(dirpath, commit_msg, git_string, commands=[]) - return True \ No newline at end of file + 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 + # ) \ No newline at end of file