diff --git a/core/models/caves.py b/core/models/caves.py index 4e963fb..db86e66 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -181,13 +181,13 @@ class Cave(TroggleModel): return QM.objects.filter(cave=self) - def new_QM_number(self, year=datetime.date.today().year): - """Given a cave and the current year, returns the next QM number.""" - try: - res=QM.objects.filter(found_by__date__year=year, found_by__cave_slug=self.slug).order_by('-number')[0] - except IndexError: - return 1 - return res.number+1 + # def new_QM_number(self, year=datetime.date.today().year): + # """Given a cave and the current year, returns the next QM number.""" + # try: + # res=QM.objects.filter(found_by__date__year=year, found_by__cave_slug=self.slug).order_by('-number')[0] + # except IndexError: + # return 1 + # return res.number+1 def kat_area(self): for a in self.area.all(): @@ -460,17 +460,17 @@ class LogbookEntry(TroggleModel): def get_previous_by_id(self): LogbookEntry.objects.get(id=self.id-1) - def new_QM_number(self): - """Returns """ - if self.cave: - nextQMnumber=self.cave.new_QM_number(self.date.year) - else: - return None - return nextQMnumber + # def new_QM_number(self): + # """Returns """ + # if self.cave: + # nextQMnumber=self.cave.new_QM_number(self.date.year) + # else: + # return None + # return nextQMnumber - def new_QM_found_link(self): - """Produces a link to a new QM with the next number filled in and this LogbookEntry set as 'found by' """ - return settings.URL_ROOT + r'/admin/core/qm/add/?' + r'found_by=' + str(self.pk) +'&number=' + str(self.new_QM_number()) + # def new_QM_found_link(self): + # """Produces a link to a new QM with the next number filled in and this LogbookEntry set as 'found by' """ + # return settings.URL_ROOT + r'/admin/core/qm/add/?' + r'found_by=' + str(self.pk) +'&number=' + str(self.new_QM_number()) def DayIndex(self): return list(self.expeditionday.logbookentry_set.all()).index(self) @@ -480,16 +480,18 @@ class QM(TroggleModel): "Number","Grade","Area","Description","Page reference","Nearest station","Completion description","Comment" """ cave = models.ForeignKey(Cave, related_name='QMs',blank=True, null=True,on_delete=models.SET_NULL ) + 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_off_by = models.ForeignKey(LogbookEntry, related_name='QMs_ticked_off',blank=True, null=True,on_delete=models.SET_NULL) - number = models.IntegerField(help_text="this is the sequential number in the year", ) + 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'), ('B', 'B: Average lead'), ('C', 'C: Tight unpromising lead'), ('D', 'D: Dig'), ('X', 'X: Unclimbable aven') - ) # also seen "?" + ) # also seen "?" in imported data - see urls.py grade = models.CharField(max_length=1, choices=GRADE_CHOICES) location_description = models.TextField(blank=True) nearest_station_description = models.CharField(max_length=400,blank=True, null=True) @@ -498,26 +500,21 @@ class QM(TroggleModel): area = models.CharField(max_length=100,blank=True, null=True) completion_description = models.TextField(blank=True,null=True) comment=models.TextField(blank=True,null=True) - blockname=models.TextField(blank=True,null=True) def __str__(self): return f'{self.code()}' def code(self): - if self.found_by: - return f'{str(self.found_by.cave_slug)[5:]}-{self.found_by.date.year}-{self.blockname}{self.number}{self.grade}' - else: - return f'{self.cave.slug()[5:]}-xxxx-{self.blockname}{self.number}{self.grade}' - + return f'{str(self.found_by.cave_slug)[5:]}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' + + def newslug(self): + qmslug = f'{str(self.cave)}-{self.expoyear}-{self.blockname}{self.number}{self.grade}' + return qmslug + def get_absolute_url(self): - if self.found_by: - qmyear = self.found_by.date.year - else: - qmyear = "1986" # HACK to check if other bits work #return settings.URL_ROOT + '/cave/' + self.found_by.cave.kataster_number + '/' + str(self.found_by.date.year) + '-' + '%02d' %self.number - return urljoin(settings.URL_ROOT, reverse('qm',kwargs={'cave_id':self.cave.slug(),'year':qmyear, 'blockname':self.blockname,'qm_id':self.number,'grade':self.grade})) + return urljoin(settings.URL_ROOT, reverse('qm',kwargs={'cave_id':self.cave.slug(),'year':self.expoyear, 'blockname':self.blockname,'qm_id':self.number,'grade':self.grade})) - def get_next_by_id(self): return QM.objects.get(id=self.id+1) diff --git a/core/views/caves.py b/core/views/caves.py index 1b47c39..616e69f 100644 --- a/core/views/caves.py +++ b/core/views/caves.py @@ -481,26 +481,48 @@ def caveQMs(request, slug): else: return render(request,'cave_qms.html', {'cave': cave}) -def qm(request,cave_id,qm_id,year,grade=None, blockname=""): +def qm(request,cave_id,qm_id,year,grade=None, blockname=None): '''Reports on one specific QM - Fixed and working July 2022, for both CSV imported QMs and for survex-imported QMs, + Fixed and working July 2022, for both CSV imported QMs needs refactoring though. + For survex-imported QMs we are not getting unique objects returned, so the query needs fixing. ''' year=int(year) - - try: - c=getCave(cave_id) - manyqms=c.get_QMs() - qm=manyqms.get(number=qm_id,found_by__date__year=year, found_by__cave_slug=c.slug()) - return render(request,'qm.html', {'qm': qm}) - except QM.DoesNotExist: - return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) - except MultipleObjectsReturned: - qm = manyqms.filter(blockname = blockname) # we could still get multiple objects.. - if qm: + + if blockname == 'None': + # CSV import QMs, use old technique + try: + c=getCave(cave_id) + manyqms=c.get_QMs() + qm=manyqms.get(number=qm_id,found_by__date__year=year, found_by__cave_slug=c.slug()) return render(request,'qm.html', {'qm': qm}) - else: + except QM.DoesNotExist: return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) + + else: + # survex import QMs, need to disambiguate with blockname + # slug = f'{str(self.cave)}-{self.found_by.date.year}-{self.blockname}{self.number}{self.grade}' + + try: + qmslug = f'{cave_id}-{year}-{blockname=}{qm_id}{grade}' + c=getCave(cave_id) + manyqms=c.get_QMs() + qm=manyqms.get(found_by__date__year=year, blockname=blockname, number=qm_id, grade=grade) + if qm: + print(qm, f'{qmslug=}:{cave_id=} {year=} {qm_id=} {blockname=} {qm.expoyear=}') + return render(request,'qm.html', {'qm': qm}) + else: + return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) + except MultipleObjectsReturned: + if len(qm) > 1: + for q in qm: + print(qm) + return render(request,'qm.html', {'qm': qm[0]}) + else: + return render(request,'qm.html', {'qm': qm}) + except QM.DoesNotExist: + return render(request,'errors/badslug.html', {'badslug': f'{cave_id=} {year=} {qm_id=} {blockname=}'}) + def get_qms(request, caveslug): '''Does not crash, but just returns a text list of the entrances for a cave. diff --git a/parsers/QMs.py b/parsers/QMs.py index ca6583b..ab9ec0f 100644 --- a/parsers/QMs.py +++ b/parsers/QMs.py @@ -103,14 +103,17 @@ def parseCaveQMs(cave,inputFile): newQM.comment=line[6] try: + # year and number are unique for a cave in CSV imports preexistingQM=QM.objects.get(number=QMnum, found_by__date__year=year) #if we don't have this one in the DB, save it - if preexistingQM.new_since_parsing==False: #if the pre-existing QM has not been modified, overwrite it + if preexistingQM.new_since_parsing==False: #if the pre-existing QM has not been modified, overwrite it - VERY OLD THING preexistingQM.delete() + newQM.expoyear = year newQM.save() else: # otherwise, print that it was ignored print((" - preserving " + str(preexistingQM) + ", which was edited in admin \r")) except QM.DoesNotExist: #if there is no pre-existing QM, save the new one + newQM.expoyear = year newQM.save() nqms += 1 except KeyError: #check on this one @@ -143,17 +146,22 @@ def parse_KH_QMs(kh, inputFile): # print(message) # DataIssue.objects.create(parser='QMs', message=message) lookupArgs={ + # inadequate now that the sequence numbers are not unique for survex-parsed QMs 'found_by':placeholder, - 'number':res['number'] + 'expoyear':year, + 'number':res['number'], + 'cave': kh, + 'grade':res['grade'] } nonLookupArgs={ - 'cave': kh, - 'grade':res['grade'], 'nearest_station_name':res['nearest_station'], 'location_description':res['description'] } - - save_carefully(QM,lookupArgs,nonLookupArgs) + instance, created = save_carefully(QM,lookupArgs,nonLookupArgs) + if created: + message = " ! - "+ instance.code() + " QM entry for '161 KH' created. " + print(message) + DataIssue.objects.create(parser='QMs', message=message) nqms += 1 return nqms diff --git a/parsers/survex.py b/parsers/survex.py index 1390991..fa92924 100644 --- a/parsers/survex.py +++ b/parsers/survex.py @@ -557,8 +557,8 @@ class LoadingSurvex(): entry_type="DUMMY", expedition_id=1, defaults={"date": survexblock.date,"cave_slug":caveslug, "slug": logslug}) - print(insp+message) - DataIssue.objects.create(parser='survex', message=message) + # print(insp+message) + # DataIssue.objects.create(parser='survex', message=message) try: qm = QM.objects.create(number=qm_no, @@ -569,6 +569,7 @@ class LoadingSurvex(): location_description=qm_notes, blockname = blockname, # only set for survex-imported QMs found_by = placeholder, + expoyear = str(survexblock.date.year), cave = survexblock.survexfile.cave) qm.save # message = " ! QM{} '{}' CREATED in DB in '{}'".format(qm_no, qm_nearest,survexblock.survexfile.path) diff --git a/urls.py b/urls.py index 462f696..e373a42 100644 --- a/urls.py +++ b/urls.py @@ -177,7 +177,8 @@ trogglepatterns = [ # QMs pages - must precede other /caves pages? re_path(r'^cave/qms/([^/]+)/?$', caveQMs, name="caveQMs"), # Fixed. July 2022 - re_path(r'^cave/qms/(?P[^/]+)/(?P\d\d\d\d)-(?P[^0-9]*)?(?P\d*)(?P[ABCDXV\?]?)?$', qm, name="qm"), # Fixed. July 2022 + re_path(r'^cave/qms/(?P[^/]+)/(?P\d\d\d\d)-(?P[^0-9]*)?(?P\d*)(?P[ABCDXV\?]?)?$', qm, name="qm"), # Dogs breakfast + # the resolution of a QM uses several fields together, there is no clean slug field. Artefact of history. # Prospecting Guide document re_path(r'^prospecting_guide/$', prospecting), # disabled. Bad links, incompatible image package use and very, very out of date.