From 549c1649b4037cad11c5d7ae7ef24c10b90879e7 Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Wed, 20 Jul 2022 14:44:56 +0300 Subject: [PATCH] QMs now have working url to survexfile & tick description --- core/models/caves.py | 38 ++++++++++++++++++++++++++++++++------ core/views/caves.py | 23 ++++++++++++----------- parsers/QMs.py | 37 ++++++++++++++++--------------------- parsers/survex.py | 5 +++-- templates/cave_qms.html | 23 ++++++++++++++++------- templates/qm.html | 19 ++++++++++++------- 6 files changed, 91 insertions(+), 54 deletions(-) diff --git a/core/models/caves.py b/core/models/caves.py index e635023..ea312df 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -4,6 +4,7 @@ import datetime import re import json import subprocess +import operator from collections import defaultdict from pathlib import Path @@ -149,7 +150,21 @@ class Cave(TroggleModel): return str(self.slug()) def get_QMs(self): - return QM.objects.filter(cave=self) + '''Searches for all QMs that reference this cave. Probably a better Django way to do this + ''' + qms = QM.objects.filter(cave=self).order_by('expoyear', 'block__date') # a QuerySet, see https://docs.djangoproject.com/en/4.0/ref/models/querysets/#order-by + return qms # a QuerySet + # undated = [] + # dated = [] + # qms = QM.objects.filter(cave=self) # a QuerySet + # for q in qms: + # if q.block: + # dated.append(q) + # else: + # undated.append(q) + # sortedqms = sorted(dated, key=operator.attrgetter('block.date')) # sort by date of survexblock the QM was defined in + # orderedqms = sorted(undated, key=operator.attrgetter('expoyear')) # sort by date of expoyear + # return orderedqms + sortedqms # a list, NOT a QuerySet # def new_QM_number(self, year=datetime.date.today().year): @@ -456,8 +471,8 @@ class QM(TroggleModel): blockname=models.TextField(blank=True,null=True) # NB truncated copy of survexblock name expoyear = models.CharField(max_length=4,blank=True, null=True) # could change to datetime if logbooks similarly chnaged found_by = models.ForeignKey(LogbookEntry, related_name='QMs_found',blank=True, null=True,on_delete=models.SET_NULL ) - ticked = models.BooleanField(default=False) # for ticked QMs not atatched to a logbook entry - ticked_off_by = models.ForeignKey(LogbookEntry, related_name='QMs_ticked_off',blank=True, null=True,on_delete=models.SET_NULL) + ticked = models.BooleanField(default=False) # for ticked QMs not attached to a logbook entry, should imply completion_description has text + ticked_off_by = models.ForeignKey(LogbookEntry, related_name='QMs_ticked_off',blank=True, null=True,on_delete=models.SET_NULL) # unused, ever?! number = models.IntegerField(help_text="this is the sequential number in the year, only unique for CSV imports", ) GRADE_CHOICES=( ('A', 'A: Large obvious lead'), @@ -493,9 +508,20 @@ class QM(TroggleModel): blocknamestr = "" #return f'{self.cave.slug()[5:]}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' return f'{cavestr}-{expoyearstr}-{blocknamestr}{self.number}{self.grade}' - - def newslug(self): - + + def get_completion_url(self): + '''assumes html file named is in same folder as cave description file + ''' + cd = None + if self.completion_description: + try: + dir = Path(self.cave.url).parent + cd = dir / self.completion_description + except: + cd = None + return cd + + def newslug(self): qmslug = f'{str(self.cave)}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' return qmslug diff --git a/core/views/caves.py b/core/views/caves.py index 033d073..0e4b4e8 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -272,14 +272,12 @@ def cavepage(request, karea, subpath): r = rendercave(request, cave, cave.slug()) return r except NoReverseMatch: - raise - except: - raise message = f'Failed to render cave: {kpath} (it does exist and is unique) because of a Django URL resolution error. Check urls.py.' return render(request,'errors/generic.html', {'message': message}) - - # return rendercave(request, cave, cave.slug(), cave_id=cave_id) - + except: + # anything else is a new problem. Add in specific error messages here as we discover new types of error + raise + def caveEntrance(request, slug): try: cave = Cave.objects.get(caveslug__slug = slug) @@ -482,6 +480,7 @@ def qm(request,cave_id,qm_id,year,grade=None, blockname=None): 290 has several QMS with the same number, grade, year (2108) and first 8 chars of the survexblock. This crashes things. ''' + year=int(year) if blockname == '': @@ -492,12 +491,13 @@ def qm(request,cave_id,qm_id,year,grade=None, blockname=None): qm=manyqms.get(number=qm_id,expoyear=year) return render(request,'qm.html', {'qm': qm}) except QM.DoesNotExist: - raise + #raise return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) else: try: qmslug = f'{cave_id}-{year}-{blockname=}{qm_id}{grade}' + print(f'{qmslug=}') c=getCave(cave_id) manyqms=c.get_QMs() qmqs=manyqms.filter(expoyear=year, blockname=blockname, number=qm_id, grade=grade) @@ -509,15 +509,16 @@ def qm(request,cave_id,qm_id,year,grade=None, blockname=None): else: qm=qmqs.get(expoyear=year, blockname=blockname, number=qm_id, grade=grade) if qm: - print(qm, f'{qmslug=}:{cave_id=} {year=} {qm_id=} {blockname=} {qm.expoyear=}') + print(qm, f'{qmslug=}:{cave_id=} {year=} {qm_id=} {blockname=} {qm.expoyear=} {qm.completion_description=}') return render(request,'qm.html', {'qm': qm}) else: - raise + #raise return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) except MultipleObjectsReturned: - raise + message = f'Multiple QMs with the same cave, year, number, grade AND first 8 chars of the survexblock name. (Could be caused by incomplete databasereset). Fix this in the survex file(s). {cave_id=} {year=} {qm_id=} {blockname=}' + return render(request,'errors/generic.html', {'message': message}) except QM.DoesNotExist: - raise + #raise return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) diff --git a/parsers/QMs.py b/parsers/QMs.py index 2aa9bbf..484499a 100644 --- a/parsers/QMs.py +++ b/parsers/QMs.py @@ -9,14 +9,16 @@ from troggle.core.models.troggle import DataIssue from troggle.core.models.caves import QM, Cave, LogbookEntry from troggle.core.utils import save_carefully -'''Reads the CSV files containg QMs for a select few caves''' +'''Reads the CSV files containg QMs for a select few caves +See parsers/survex.py for the parser which extracts QMs from the survex files +''' def deleteQMs(): QM.objects.all().delete() DataIssue.objects.filter(parser='QMs').delete() -def parseCaveQMs(cave,inputFile): +def parseCaveQMs(cave, inputFile, ticked=False): """Runs through the CSV file at inputFile (which is a relative path from expoweb) and saves each QM as a QM instance. This is creating and linking a Placeholder logbookentry dated 1st Jan. in the relevant @@ -59,7 +61,7 @@ def parseCaveQMs(cave,inputFile): message = f' ! - {qmPath} KH is not in the database. Please run cave parser' print(message) DataIssue.objects.create(parser='QMs', message=message) - nqms = parse_KH_QMs(kh, inputFile=inputFile) + nqms = parse_KH_QMs(kh, inputFile=inputFile, ticked=ticked) return nqms #qmPath = settings.EXPOWEB+inputFile @@ -77,16 +79,6 @@ def parseCaveQMs(cave,inputFile): n += 1 year=int(line[0][1:5]) logslug = f'PH_{int(year)}_{int(n):02d}' - # logbook placeholder code was previously here. No longer needed. - #check if placeholder exists for given year, create it if not - # message = " ! - "+ str(year) + " logbook: placeholder entry for '" + cave + "' created. DUMMY EXPEDITION ID. Should be re-attached to the actual trip." - # if cave=='204-steinBH': - # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="204", title="placeholder for QMs in 204", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(steinBr), "slug": logslug}) - # elif cave=='234-Hauch': - # placeholder, hadToCreate = LogbookEntry.objects.get_or_create(date__year=year, place="234", title="placeholder for QMs in 234", text=message, entry_type="DUMMY", expedition_id=1, defaults={"date": date(year, 1, 1),"cave_slug":str(hauchHl)}) - # # if hadToCreate: - # # print(message) - # # DataIssue.objects.create(parser='QMs', message=message) QMnum=re.match(r".*?-\d*?-X?(?P\d*)",line[0]).group("numb") newQM = QM() # newQM.found_by=placeholder @@ -100,12 +92,13 @@ def parseCaveQMs(cave,inputFile): newQM.area=line[2] newQM.location_description=line[3] - # Troggle will in future (?! - written in 2006) check if QMs are completed by checking if they have a ticked_off_by trip. - # In the table, completion is indicated by the presence of a completion discription. + # In the table, completion is indicated by the presence of a completion discription. newQM.completion_description=line[4] newQM.nearest_station_description=line[5] - # if newQM.completion_description: - # newQM.ticked_off_by=placeholder + if newQM.completion_description: + newQM.ticked = True + else: + newQM.ticked = False newQM.comment=line[6] try: @@ -134,7 +127,7 @@ def parseCaveQMs(cave,inputFile): continue return nqms -def parse_KH_QMs(kh, inputFile): +def parse_KH_QMs(kh, inputFile, ticked): """import QMs from the 1623-161 (Kaninchenhohle) html pages, different format """ khQMs=open(os.path.join(settings.EXPOWEB, inputFile),'r') @@ -161,12 +154,13 @@ def parse_KH_QMs(kh, inputFile): 'grade':res['grade'] } nonLookupArgs={ + 'ticked': ticked, 'nearest_station_name':res['nearest_station'], 'location_description':res['description'] } instance, created = save_carefully(QM,lookupArgs,nonLookupArgs) # if created: - # message = " ! - "+ instance.code() + " QM entry for '161 KH' created. " + # message = f" ! - {instance.code()} QM entry for '161 KH' created. ticked: {ticked}" # print(message) # DataIssue.objects.create(parser='QMs', message=message) nqms += 1 @@ -177,8 +171,9 @@ def Load_QMs(): deleteQMs() n204 = parseCaveQMs(cave='204-steinBH',inputFile=r"1623/204/qm.csv") n234 = parseCaveQMs(cave='234-Hauch',inputFile=r"1623/234/qm.csv") - n161 = parseCaveQMs(cave='161-KH', inputFile="1623/161/qmtodo.htm") + n161 = parseCaveQMs(cave='161-KH', inputFile="1623/161/qmtodo.htm", ticked=False) + t161 = parseCaveQMs(cave='161-KH', inputFile="1623/161/qmdone.htm", ticked=True) #parseCaveQMs(cave='balkonhoehle',inputFile=r"1623/264/qm.csv") - print(f" - Imported: {n204} QMs for 204, {n234} QMs for 234, {n161} QMs for 161.") + print(f" - Imported: {n204} QMs for 204, {n234} QMs for 234, {t161} QMs for 161 done, {n161} QMs for 161 not done.") print () diff --git a/parsers/survex.py b/parsers/survex.py index e1e017a..942dbe9 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -545,8 +545,8 @@ class LoadingSurvex(): caveslug = survexblock.survexfile.cave.slug() place = survexblock.survexfile.cave else: - caveslug = "ugh" - place = "oops" + caveslug = None + place = None # message = f' ! - logbook dummy "{logslug}" {str(survexblock.date)[:11]} for cave "{caveslug}" created.' @@ -568,6 +568,7 @@ class LoadingSurvex(): nearest_station_name=qm_nearest, grade=qm_grade.upper(), location_description=qm_notes, + block = survexblock, # only set for survex-imported QMs blockname = blockname, # only set for survex-imported QMs # found_by = placeholder, expoyear = str(survexblock.date.year), diff --git a/templates/cave_qms.html b/templates/cave_qms.html index c5bde56..358d098 100644 --- a/templates/cave_qms.html +++ b/templates/cave_qms.html @@ -7,8 +7,8 @@

Note that QMs loaded for 1623-161, 1623-204 and 1623-234 are imported from CSV files .

QMs are also loaded directly from the survex files, e.g. see @@ -24,20 +24,29 @@ {% block content %}

Extant

{% if cave.get_QMs %} -