Fixing URLs for cave descriptions

This commit is contained in:
Philip Sargent 2022-03-18 20:00:15 +00:00
parent 6f32364675
commit 6a18511dd0
9 changed files with 110 additions and 82 deletions

View File

@ -158,14 +158,30 @@ class PageTests(TestCase):
self.assertEqual(len(response.content), 6057)
def test_cave_kataster_not_found(self):
# database not loaded, so no caves found
response = self.client.get('/cave/115')
self.assertEqual(response.status_code, 200)
# database not loaded, so no caves found; so looks for a generic expopage and fails
response = self.client.get('/1623/115.htm')
self.assertEqual(response.status_code, 404)
content = response.content.decode()
ph = r"Cave Identifier not found in database"
ph = r"Page not found 1623/115.htm"
phmatch = re.search(ph, content)
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
def test_caves_page(self):
response = self.client.get('/caves')
self.assertEqual(response.status_code, 200)
content = response.content.decode()
ph = r"Cave Number Index - kept updated"
phmatch = re.search(ph, content)
self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'")
def test_caves_page_kataster_not_found(self):
response = self.client.get('/caves')
self.assertEqual(response.status_code, 200)
content = response.content.decode()
ph = r"115"
phmatch = re.search(ph, content)
self.assertIsNone(phmatch, "Failed to find expected text: '" + ph +"'")
def test_page_ss(self):
response = self.client.get('/survey_scans/')
self.assertEqual(response.status_code, 200)

View File

@ -37,7 +37,7 @@ class FixtureTests(TestCase):
def test_fix_cave_loaded115(self):
c = Cave.objects.get(kataster_number='115')
self.assertEqual(str(c.description_file), "1623/115.htm")
self.assertEqual(str(c.url), "1623/115.htm")
self.assertEqual(str(c.url), "1623/115.url") # intentional
self.assertEqual(str(c.filename), "1623-115.html")
# c.area is a 'ManyRelatedManager' object and not iterable
@ -135,7 +135,7 @@ class FixturePageTests(TestCase):
def test_fix_cave_url115(self):
ph = self.ph
response = self.client.get('/1623/115.htm')
response = self.client.get('/1623/115.url') # yes this is intentional, see the inserted data above & fixture
self.assertEqual(response.status_code, 200)
content = response.content.decode()

View File

@ -14,7 +14,7 @@
"notes": "The Austrian Kataster has adopted a very perverse way of numbering things. Their numbers are as follows:</p><ul> <li>115a&nbsp;&nbsp;&nbsp;Stellerwegh&ouml;hle entrance&nbsp;&nbsp;&nbsp;41a</li> <li>115b&nbsp;&nbsp;&nbsp;Stellerwegh&ouml;hle entrance&nbsp;&nbsp;&nbsp;41b</li> <li>115c&nbsp;&nbsp;&nbsp;Stellerwegh&ouml;hle entrance&nbsp;&nbsp;&nbsp;41c ( where ? )</li> <li>115d&nbsp;&nbsp;&nbsp;Schnellzugh&ouml;hle entrance&nbsp;&nbsp;&nbsp;115</li> <li>115e&nbsp;&nbsp;&nbsp;unnamed entrance&nbsp;&nbsp;&nbsp;142</li></ul><p>", "length": "SMK system total 54000m", "depth": "from entrance; SMK system total 1032m", "extent": "SMK system total 2812m",
"survex_file": "smk-system.svx",
"description_file": "1623/115.htm",
"url": "1623/115.htm",
"url": "1623/115.url",
"filename": "1623-115.html",
"area": [1, 8]}},

View File

@ -211,17 +211,21 @@ def rendercave(request, cave, slug, cave_id=''):
'''Gets the data and files ready and then triggers Django to render the template.
The resulting html contains urls which are dispatched independently, e.g. the 'download' link
'''
#print(" ! rendercave:'{}' slug:'{}' cave_id:'{}'".format(cave, slug, cave_id))
# print(" ! rendercave:'{}' START slug:'{}' cave_id:'{}'".format(cave, slug, cave_id))
if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
return render(request, 'nonpublic.html', {'instance': cave, 'cavepage': True, 'cave_id': cave_id})
else:
svxstem = Path(cave.survex_file).parent / Path(cave.survex_file).stem
svx3d = Path(cave.survex_file).stem
# print(f" ! rendercave: slug:'{slug}' survex file:'{cave.survex_file}'")
try:
svx3d = Path(cave.survex_file).stem
svxstem = Path(settings.SURVEX_DATA) / Path(cave.survex_file)
# print(f" ! rendercave: slug:'{slug}' '' ++ '{svxstem}'")
except:
print(f" ! rendercave: slug:'{slug}' FAIL TO MANAGE survex file:'{cave.survex_file}'")
# NOTE the template itself loads the 3d file using javascript before it loads anything else.
# Django cannot see what this javascript is doing, so we need to ensure that the 3d file exists first.
# So only do this render if a valid .3d file exists. TO BE DONE
# So only do this render if a valid .3d file exists. TO BE DONE -Not yet as CaveView is currently disabled
# see design docum in troggle/templates/cave.html
# see rendercave() in troggle/core/views/caves.py
templatefile = 'cave.html'
@ -229,40 +233,47 @@ def rendercave(request, cave, slug, cave_id=''):
editable = True
else:
editable = False
#print(f" ! rendercave:'{cave}' using template '{templatefile}' svxstem:'{svxstem}' caveid:'{cave_id}' svx3d:'{svx3d}'")
if not cave_id:
cave_id = slug # cave.unofficial_number
try:
r = render(request,templatefile, {'cave_editable': editable, 'settings': settings, 'cave': cave, 'cavepage': True,
'cave_id': cave_id, 'svxstem': svxstem, 'svx3d':svx3d})
context = {'cave_editable': editable, 'settings': settings, 'cave': cave, 'cavepage': True,
'cave_id': cave_id, 'svxstem': str(svxstem), 'svx3d':svx3d}
r = render(request, templatefile, context) # crashes here if url not set up for 'edit_cave' in urls.py
return r
except:
raise
message = f'Failed to render cave: {slug}'
return render(request,'errors/generic.html', {'message': message})
def cavepage(request, karea, subpath):
'''Displays a cave description page
accessed by kataster area number specifically
OR
accessed by cave.url specifically set in data, e.g.
"1623/000/000.html" <= cave-data/1623-000.html
"1623/41/115.htm" <= cave-data/1623-115.html
so we have to query the database to fine the URL as we cannot rely on the url actually telling us the cave by inspection.
There are A LOT OF URLS to e.g. /1623/161/l/rl89a.htm which are IMAGES and html files
in cave descriptions. These need to be handled HERE
'''
path = karea + subpath
#print(" ! cavepage:'{}' kataster area:'{}' rest of path:'{}'".format(path, karea, subpath))
kpath = karea + subpath
# print(f" ! cavepage:'{kpath}' kataster area:'{karea}' rest of path:'{subpath}'")
try:
cave = Cave.objects.get(url = path) # ideally this will be unique
return rendercave(request, cave, cave.slug())
cave = Cave.objects.get(url = kpath) # ideally this will be unique
# print(f" ! cavepage: url={kpath} -- {cave}")
r = rendercave(request, cave, cave.slug())
return r
except Cave.DoesNotExist:
# probably a link to text or an image e.g. 1623/161/l/rl89a.htm i.e. an expoweb page
return expo.expopage(request, path)
return expo.expopage(request, str(kpath))
except Cave.MultipleObjectsReturned:
caves = Cave.objects.filter(url = path)
caves = Cave.objects.filter(url = kpath)
# we should have a -several variant for the cave pages, not just the svxcaves:
return render(request, 'svxcaveseveral.html', {'settings': settings, "caves":caves })
except:
message = f'Failed to find cave: {path}'
message = f'Failed to find cave: {kpath}'
return render(request,'errors/generic.html', {'message': message})
def cave(request, cave_id='', offical_name=''):
@ -292,27 +303,16 @@ def caveEntrance(request, slug):
else:
return render(request,'cave_entrances.html', {'cave': cave})
def caveDescription(request, slug):
try:
cave = Cave.objects.get(caveslug__slug = slug)
except:
return render(request,'errors/badslug.html', {'badslug': slug})
# def caveDescription(request, slug):
# try:
# cave = Cave.objects.get(caveslug__slug = slug)
# except:
# return render(request,'errors/badslug.html', {'badslug': slug})
if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
return render(request,'nonpublic.html', {'instance': cave})
else:
return render(request,'cave_uground_description.html', {'cave': cave})
def caveQMs(request, slug):
try:
cave = Cave.objects.get(caveslug__slug = slug)
except:
return render(request,'errors/badslug.html', {'badslug': slug})
if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
return render(request,'nonpublic.html', {'instance': cave})
else:
return render(request,'cave_qms.html', {'cave': cave})
# if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
# return render(request,'nonpublic.html', {'instance': cave})
# else:
# return render(request,'cave_uground_description.html', {'cave': cave})
@login_required_if_public
def edit_cave(request, slug=None):
@ -456,21 +456,6 @@ def edit_entrance(request, caveslug=None, slug=None):
'entletter': entletter
})
def qm(request,cave_id,qm_id,year,grade=None):
year=int(year)
try:
qm=getCave(cave_id).get_QMs().get(number=qm_id,found_by__date__year=year)
return render(request,'qm.html',locals())
except Cave.MultipleObjectsReturned: # entirely the wrong action, REPLACE with the right display
caves = Cave.objects.filter(kataster_number=cave_id)
return render(request, 'svxcaveseveral.html', {'settings': settings, "caves":caves })
except QM.DoesNotExist:
url=urllib.parse.urljoin(settings.URL_ROOT, r'/admin/core/qm/add/'+'?'+ r'number=' + qm_id)
if grade:
url += r'&grade=' + grade
return HttpResponseRedirect(url)
def ent(request, cave_id, ent_letter):
cave = Cave.objects.filter(kataster_number = cave_id)[0]
cave_and_ent = CaveAndEntrance.objects.filter(cave = cave).filter(entrance_letter = ent_letter)[0]
@ -497,6 +482,32 @@ def get_entrances(request, caveslug):
return render(request,'errors/badslug.html', {'badslug': caveslug})
return render(request,'options.html', {"items": [(e.entrance.slug(), e.entrance.slug()) for e in cave.entrances()]})
def caveQMs(request, slug):
try:
cave = Cave.objects.get(caveslug__slug = slug)
except:
return render(request,'errors/badslug.html', {'badslug': slug})
if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
return render(request,'nonpublic.html', {'instance': cave})
else:
return render(request,'cave_qms.html', {'cave': cave})
def qm(request,cave_id,qm_id,year,grade=None):
year=int(year)
try:
qm=getCave(cave_id).get_QMs().get(number=qm_id,found_by__date__year=year)
return render(request,'qm.html',locals())
except Cave.MultipleObjectsReturned: # entirely the wrong action, REPLACE with the right display
caves = Cave.objects.filter(kataster_number=cave_id)
return render(request, 'svxcaveseveral.html', {'settings': settings, "caves":caves })
except QM.DoesNotExist:
url=urllib.parse.urljoin(settings.URL_ROOT, r'/admin/core/qm/add/'+'?'+ r'number=' + qm_id)
if grade:
url += r'&grade=' + grade
return HttpResponseRedirect(url)
def get_qms(request, caveslug):
try:
cave = Cave.objects.get(caveslug__slug = caveslug)

View File

@ -115,15 +115,16 @@ def scanupload(request, path=None):
return(oldwallet(request, path))
if str(wallet).lower().endswith('indexpages'):
print(f'! - FORM scanupload - start {wallet} REDIRECT TO OLDWALLET')
# print(f'! - FORM scanupload - start {wallet} REDIRECT TO OLDWALLET')
return(walletindex(request, path))
if not re.match('(19|20)\d\d[:#]\d\d', wallet):
wallet = "2022:01" # improve this later
print(f'! - FORM scanupload - start {wallet}')
# print(f'! - FORM scanupload - start {wallet}')
if path:
print(f'! - FORM scanupload - start wallet:{wallet}: path:{path}:')
pass
# print(f'! - FORM scanupload - start wallet:{wallet}: path:{path}:')
if int(year) < 1977:
year = "1977"
if int(year) > 2050:

View File

@ -32,7 +32,7 @@
<p>If you can see a filename here: [&nbsp;<a href="/survexfile/{{cave.survex_file}}">{{cave.survex_file}}</a> &nbsp;]
which does <em>not</em> match any in the list below <em>including the directories beginning with </em><strong>caves-162X/</strong></em>
not just the filename</em>, then (if logged on) you can
<strong>click here <var><a href="/cave/{{cave.slug}}/edit/">/cave/{{cave.slug}}/edit</a></var></strong>
<strong>click here <var><a href="{{cave.slug}}_cave_edit/">/{{cave.slug}}_cave_edit</a></var></strong>
to go to a form to correct the online data.
Instructions for filling in this form are in this part
<a href="/handbook/survey/caveentry.html"> of the survey handbook</a>.

View File

@ -32,7 +32,7 @@ All the processing to extract the survex subdriectories and survex files is done
</p>
<p>If you can see a filename here: [&nbsp;<a href="/survexfile/{{cave.survex_file}}">{{cave.survex_file}}</a> &nbsp;] which does <em>not</em> match any in the list below <em>including the directories beginning with </em><strong>caves-162X/</strong></em>
not just the filename</em>, then (if logged on) you can
<strong>click here <var><a href="/cave/{{cave.slug}}/edit/">/cave/{{cave.slug}}/edit</a></var></strong>
<strong>click here <var><a href="{{cave.slug}}_cave_edit/">{{cave.slug}}_cave_edit</a></var></strong>
to go to a form to correct the online data.
Instructions for filling in this form are in this part
<a href="/handbook/survey/caveentry.html"> of the survey handbook</a>.

36
urls.py
View File

@ -7,13 +7,13 @@ from django.contrib import admin
from django.contrib import auth
from django.urls import path, reverse, resolve
from troggle.core.views import caves, statistics, survex
from troggle.core.views import statistics, survex
from troggle.core.views.scans import scansingle, allwallets
from troggle.core.views.drawings import dwgallfiles, dwgfilesingle
from troggle.core.views.uploads import dwgupload, scanupload, photoupload
from troggle.core.views.other import troggle404, frontpage, todos, controlpanel, frontpage
from troggle.core.views.other import exportlogbook
from troggle.core.views.caves import ent, cavepage
from troggle.core.views.caves import ent, cavepage, caveindex, get_entrances, get_qms, edit_cave, cave3d, caveEntrance, edit_entrance, caveQMs, qm
from troggle.core.views.logbooks import get_logbook_entries, logbookentry, logbookSearch
from troggle.core.views.logbooks import notablepersons, person, get_people
from troggle.core.views.logbooks import expedition, personexpedition, Expeditions_tsvListView, Expeditions_jsonListView
@ -78,8 +78,8 @@ trogglepatterns = [
path('expofiles/', include(expofilesurls)), # intercepted by Apache, if it is running.
path('expofiles', include(expofilesurls)), # curious interaction with the include() here, not just a slash problem.
re_path(r'^caves$', caves.caveindex, name="caveindex"),
re_path(r'^indxal.htm$', caves.caveindex, name="caveindex"), # ~420 hrefs to this url in expoweb files
re_path(r'^caves$', caveindex, name="caveindex"),
re_path(r'^indxal.htm$', caveindex, name="caveindex"), # ~420 hrefs to this url in expoweb files
re_path(r'^people/?$', notablepersons, name="notablepersons"),
re_path(r'^admin/doc/', include('django.contrib.admindocs.urls')), # needs docutils Python module (http://docutils.sf.net/).
@ -119,25 +119,25 @@ trogglepatterns = [
# Internal. editfile.html template uses these internally
re_path(r'^getPeople/(?P<expeditionslug>.*)', get_people, name = "get_people"),
re_path(r'^getLogBookEntries/(?P<expeditionslug>.*)', get_logbook_entries, name = "get_logbook_entries"),
re_path(r'^getQMs/(?P<caveslug>.*)', caves.get_qms, name = "get_qms"),
re_path(r'^getEntrances/(?P<caveslug>.*)', caves.get_entrances, name = "get_entrances"),
re_path(r'^getQMs/(?P<caveslug>.*)', get_qms, name = "get_qms"),
re_path(r'^getEntrances/(?P<caveslug>.*)', get_entrances, name = "get_entrances"),
# Cave description pages
re_path(r'^newcave/$', caves.edit_cave, name="newcave"),
re_path(r'^cave/3d/(?P<cave_id>[^/]+)$', caves.cave3d, name="cave3d"),
re_path(r'^newcave/$', edit_cave, name="newcave"),
re_path(r'^cave/3d/(?P<cave_id>[^/]+)$', cave3d, name="cave3d"),
re_path(r'^cave/description/([^/]+)/?$', caves.caveDescription), #!!!BAD, local links fail..
re_path(r'^cave/(?P<cave_id>[^/]+)/?$', caves.cave, name="cave"), #!!!BAD, local links fail.. to be checked..
re_path(r'^cave/(?P<cave_id>[^/]+)/?(?P<ent_letter>[^/])$', ent), #!!!BAD, local links fail..# view_caves.ent
re_path(r'^cave/(?P<slug>[^/]+)/edit/$', caves.edit_cave, name="edit_cave"),
re_path(r'^(?P<karea>\d\d\d\d)(?P<subpath>.*)$', cavepage, name="cavepage"), # shorthand /1623/264
#re_path(r'^cave/description/([^/]+)/?$', caves.caveDescription), #!!!BAD, local links fail..
#re_path(r'^cave/(?P<cave_id>[^/]+)/?$', caves.cave, name="cave"), # used only in testing !? XXXXXXXXXXXXXXXXXXXXXXXXXX
#re_path(r'^cave/(?P<cave_id>[^/]+)/?(?P<ent_letter>[^/])$', ent), #!!!BAD, local links fail..# view_caves.ent
re_path(r'^(?P<slug>[^/]+)_cave_edit/$', edit_cave, name="edit_cave"), # edit_cave needed by cave.html template for url matching
re_path(r'^(?P<karea>\d\d\d\d)(?P<subpath>.*)$', cavepage, name="cavepage"), # shorthand /1623/264 or 1623/161/top.htm
# Note that urls eg '/1623/161/l/rl89a.htm' are handled by cavepage which redirects them to 'expopage'
# Note that _edit$ for a cave description page in a subfolder e.g. /1623/204/204.html_edit gets caught here and breaks with 404
# Entrances
re_path(r'^cave/entrance/([^/]+)/?$', caves.caveEntrance), # lists all entrances !!!BAD, local links fail
re_path(r'^entrance/(?P<caveslug>[^/]+)/(?P<slug>[^/]+)/edit/', caves.edit_entrance, name = "editentrance"), #edit existing entrance
re_path(r'^entrance/new/(?P<caveslug>[^/]+)$', caves.edit_entrance, name = "newentrance"), # new entrance for a cave
re_path(r'^cave/entrance/([^/]+)/?$', caveEntrance), # lists all entrances !!!BAD, local links fail
re_path(r'^entrance/(?P<caveslug>[^/]+)/(?P<slug>[^/]+)/edit/', edit_entrance, name = "editentrance"), #edit existing entrance
re_path(r'^entrance/new/(?P<caveslug>[^/]+)$', edit_entrance, name = "newentrance"), # new entrance for a cave
# System admin and monitoring
path('statistics', statistics.stats, name="stats"),
@ -174,8 +174,8 @@ trogglepatterns = [
path('dwgdataraw/<path:path>', dwgfilesingle, name="dwgfilesingle"),
# QMs pages - must precede other /caves pages?
re_path(r'^cave/qms/([^/]+)/?$', caves.caveQMs), # Broken- QMs have no proper link to cave id
re_path(r'^cave/(?P<cave_id>[^/]+)/(?P<year>\d\d\d\d)-(?P<qm_id>\d*)(?P<grade>[ABCDX]?)?$', caves.qm, name="qm"),
re_path(r'^cave/qms/([^/]+)/?$', caveQMs), # Broken- QMs have no proper link to cave id
re_path(r'^cave/(?P<cave_id>[^/]+)/(?P<year>\d\d\d\d)-(?P<qm_id>\d*)(?P<grade>[ABCDX]?)?$', qm, name="qm"),
# Prospecting Guide document
re_path(r'^prospecting_guide/$', prospecting), # disabled. Bad links, incompatible image package use and very, very out of date.