mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-24 16:21:53 +00:00
275 lines
11 KiB
Python
275 lines
11 KiB
Python
import os, stat
|
|
import re
|
|
import datetime
|
|
from pathlib import Path
|
|
from urllib.parse import urljoin, unquote as urlunquote
|
|
from urllib.request import urlopen
|
|
|
|
from django.conf import settings
|
|
from django.shortcuts import render
|
|
from django.http import HttpResponse
|
|
|
|
from troggle.core.models.survex import Wallet, SingleScan, SurvexBlock
|
|
from troggle.core.models.troggle import Person, Expedition
|
|
from troggle.core.models.troggle import DataIssue
|
|
from troggle.core.models.caves import GetCaveLookup
|
|
from troggle.core.views.expo import getmimetype
|
|
#from troggle.parsers.people import GetPersonExpeditionNameLookup
|
|
|
|
#import parsers.surveys
|
|
|
|
'''one of these views serves files as binary blobs, and simply set the mime type based on the file extension,
|
|
as does the urls.py dispatcher which sends them here. Here they should actually have the filetype checked
|
|
by looking inside the file before being served.
|
|
|
|
need to check if inavlid query string is invalid, or produces multiple replies
|
|
and render a user-friendly error page.
|
|
|
|
Note that datewallet(), caveifywallet() etc do NOT save the object to the db. They are ephemeral, just for the page rendering of the
|
|
manywallets dict.
|
|
|
|
TODO
|
|
cave for a wallet - just gets the last one, randomly. SHould make this a list or many:many ideally
|
|
|
|
add this file in to the todo list thinggy.
|
|
'''
|
|
|
|
def populatewallet(w):
|
|
'''Copy survex data here just for display, not permanently
|
|
|
|
Only gets data from the survex file when it was parsed on import..
|
|
so doesn't work if there is no *ref value
|
|
'''
|
|
survexpeople = []
|
|
blocks = SurvexBlock.objects.filter(scanswallet = w)
|
|
for b in blocks:
|
|
for personrole in b.survexpersonrole_set.all():
|
|
survexpeople.append(personrole.personname)
|
|
w.persons = list(set(survexpeople))
|
|
|
|
def datewallet(w, earliest):
|
|
first = earliest
|
|
blocks = SurvexBlock.objects.filter(scanswallet = w)
|
|
for b in blocks:
|
|
if b.date:
|
|
if b.date < first:
|
|
first = b.date
|
|
if first == earliest:
|
|
# no date found
|
|
w.date = None
|
|
else:
|
|
w.date = first.isoformat()
|
|
|
|
def caveifywallet(w):
|
|
'''Gets the cave from the list of survex files,
|
|
only selects one of them though. Only used for display.
|
|
'''
|
|
#print(f' - Caveify {w=}')
|
|
blocknames = []
|
|
blocks = SurvexBlock.objects.filter(scanswallet = w)
|
|
for b in blocks:
|
|
# NB b.cave is not populated by parser. Use b.survexfile.cave instead, or we could parse b.survexpath
|
|
if b.survexfile.cave:
|
|
w.caveobj = b.survexfile.cave # just gets the last one, randomly. SHould make this a list or many:many ideally
|
|
w.cave = w.caveobj
|
|
if b.name:
|
|
blocknames.append(b.name)
|
|
|
|
if w.name():
|
|
w.displaynames = [w.name()]
|
|
else:
|
|
w.displaynames = blocknames
|
|
|
|
def fillblankpeople(w):
|
|
# this isn't working..? why? Because it needs a *ref and an import
|
|
wp = w.people()
|
|
w.persons = wp
|
|
if not wp:
|
|
populatewallet(w)
|
|
else:
|
|
if len(wp) == 1:
|
|
# print(f' - {wp=}')
|
|
nobody = wp[0].lower()
|
|
if nobody == 'unknown' or nobody == 'nobody' or nobody == ' ' or nobody == '':
|
|
# print(f' - {wp=} {nobody=}')
|
|
populatewallet(w)
|
|
|
|
def fillblankothers(w):
|
|
earliest = datetime.datetime.now().date()
|
|
if not w.date():
|
|
datewallet(w, earliest)
|
|
|
|
Gcavelookup = GetCaveLookup()
|
|
|
|
wcaveid = w.cave()
|
|
if not wcaveid or wcaveid == "":
|
|
caveifywallet(w)
|
|
else:
|
|
if type(wcaveid) == list:
|
|
for i in wcaveid:
|
|
if i in Gcavelookup:
|
|
w.caveobj = Gcavelookup[i] # just sets it to the last one found. nasty. bug waiting to happen
|
|
#print(f' - Found cave object from id {wcaveid}')
|
|
else:
|
|
if wcaveid in Gcavelookup:
|
|
w.caveobj = Gcavelookup[wcaveid]
|
|
else:
|
|
print(f' - Failed to find cave object from id {wcaveid}')
|
|
|
|
|
|
def fixsurvextick(w, ticks):
|
|
ticks["S"] = w.fixsurvextick(ticks["S"])
|
|
|
|
|
|
def walletslistperson(request, first_name, last_name):
|
|
'''Page which displays a list of all the wallets for a specific person
|
|
HORRIBLE linear search through everything. Index and do SQL query properly
|
|
'''
|
|
# This is where we face having to re-do everything to do with names properly, rather than the horrible series of hacks over 20 years..
|
|
#GetPersonExpeditionNameLookup
|
|
def tickspersonwallet(p):
|
|
manywallets = []
|
|
wallets = Wallet.objects.all()
|
|
for w in wallets:
|
|
w.persons = w.people() # ephemeral attribute for web page
|
|
fillblankpeople(w)
|
|
if w.persons:
|
|
if p.fullname in w.persons:
|
|
manywallets.append(w)
|
|
fillblankothers(w)
|
|
w.ticks = w.get_ticks() # the complaints in colour form
|
|
fixsurvextick(w, w.ticks)
|
|
return manywallets
|
|
|
|
try:
|
|
if last_name:
|
|
p = Person.objects.get(fullname= f'{first_name} {last_name}')
|
|
else:
|
|
# special Wookey-hack
|
|
p = Person.objects.get(first_name= f'{first_name}')
|
|
except:
|
|
#raise
|
|
return render(request, 'errors/generic.html', {'message': f'Unrecognised name of a expo person: "{first_name} {last_name}"'})
|
|
|
|
manywallets = tickspersonwallet(p)
|
|
expeditions = Expedition.objects.all()
|
|
return render(request, 'personwallets.html', { 'manywallets':manywallets, 'settings': settings, 'person': p, 'expeditions': expeditions})
|
|
|
|
|
|
def walletslistyear(request, year):
|
|
'''Page which displays a list of all the wallets in a specific year
|
|
'''
|
|
def ticksyearwallet(year):
|
|
manywallets = []
|
|
wallets = Wallet.objects.all()
|
|
for w in wallets:
|
|
|
|
if year == w.year():
|
|
manywallets.append(w)
|
|
fillblankpeople(w)
|
|
fillblankothers(w)
|
|
w.ticks = w.get_ticks() # the complaints in colour form, from the json file on disc
|
|
fixsurvextick(w, w.ticks)
|
|
else:
|
|
continue
|
|
|
|
return manywallets
|
|
|
|
if year < 1976 or year > 2050:
|
|
return render(request, 'errors/generic.html', {'message': 'Year out of range. Must be between 1976 and 2050'})
|
|
else:
|
|
year = str(year)
|
|
#return render(request, 'errors/generic.html', {'message': 'This page logic not implemented yet'})
|
|
|
|
manywallets = ticksyearwallet(year)
|
|
expeditions = Expedition.objects.all()
|
|
expedition = Expedition.objects.filter(year=year)
|
|
return render(request, 'yearwallets.html', { 'manywallets':manywallets, 'settings': settings, 'year': year, 'expeditions': expeditions, 'expedition': expedition})
|
|
|
|
|
|
|
|
def cavewallets(request, caveid):
|
|
'''Returns all the wallets for just one cave
|
|
'''
|
|
Gcavelookup = GetCaveLookup()
|
|
if caveid in Gcavelookup:
|
|
cave = Gcavelookup[caveid]
|
|
else:
|
|
return render(request,'errors/badslug.html', {'badslug': caveid})
|
|
|
|
# remove duplication. Sorting is done in the template
|
|
# But this only gets wallets which have survex files attached..
|
|
wallets = set(Wallet.objects.filter(survexblock__survexfile__cave=cave))
|
|
|
|
# all the ones without a survexblock attached via a *ref, search for match in JSON
|
|
zilchwallets = set(Wallet.objects.exclude(survexblock__survexfile__cave=cave))
|
|
for z in zilchwallets:
|
|
zcaveid = z.cave()
|
|
if zcaveid:
|
|
if str(zcaveid) in Gcavelookup:
|
|
fcave = Gcavelookup[str(zcaveid)]
|
|
if str(fcave.slug()) == caveid:
|
|
# print(f' - Found one ! {z.walletname=} {zcaveid=}')
|
|
wallets.add(z)
|
|
else:
|
|
wurl = f"/scanupload/{z.walletname.replace('#',':')}"
|
|
message = f" ! In {z.walletname} there is an unrecognised cave name '{zcaveid}' (out of {len(Gcavelookup):,} cave names and aliases)"
|
|
print(message)
|
|
DataIssue.objects.update_or_create(parser='scans', message=message, url=wurl)
|
|
|
|
manywallets = list(set(wallets))
|
|
for w in manywallets:
|
|
fillblankpeople(w)
|
|
fillblankothers(w)
|
|
w.ticks = w.get_ticks() # the complaints in colour form, from the json file on disc
|
|
fixsurvextick(w, w.ticks)
|
|
expeditions = Expedition.objects.all()
|
|
return render(request, 'cavewallets.html', { 'manywallets':manywallets, 'settings': settings, 'cave': cave, 'expeditions': expeditions})
|
|
|
|
|
|
def oldwallet(request, path):
|
|
'''Now called only for non-standard wallet structures for pre-2000 wallets
|
|
'''
|
|
# print([ s.walletname for s in Wallet.objects.all() ])
|
|
print(f'! - oldwallet path:{path}')
|
|
try:
|
|
wallet = Wallet.objects.get(walletname=urlunquote(path))
|
|
return render(request, 'wallet_old.html', { 'wallet':wallet, 'settings': settings })
|
|
except:
|
|
message = f'Scan folder error or not found \'{path}\' .'
|
|
return render(request, 'errors/generic.html', {'message': message})
|
|
|
|
|
|
def scansingle(request, path, file):
|
|
'''sends a single binary file to the user for display - browser decides how using mimetype
|
|
'''
|
|
try:
|
|
wallet = Wallet.objects.get(walletname=urlunquote(path))
|
|
singlescan = SingleScan.objects.get(wallet=wallet, name=file)
|
|
imagefile = Path(singlescan.ffile, file)
|
|
if imagefile.is_file():
|
|
message = f" - scansingle {imagefile} {path}:{file}:{getmimetype(file)}:"
|
|
print(message)
|
|
return HttpResponse(content=open(imagefile,"rb"), content_type=getmimetype(file)) # any type of image
|
|
else:
|
|
message = f'Scan folder file \'{imagefile}\' not found. {path=} {file=}'
|
|
print(message)
|
|
return render(request, 'errors/generic.html', {'message': message})
|
|
|
|
except:
|
|
message = f'Scan folder or scan item access error \'{path}\' and \'{file}\'.'
|
|
return render(request, 'errors/generic.html', {'message': message})
|
|
|
|
|
|
def allscans(request):
|
|
'''Returns all the wallets in the system, we would like to use
|
|
the Django queryset SQL optimisation https://docs.djangoproject.com/en/3.2/ref/models/querysets/#prefetch-related
|
|
to get the related singlescan and survexblock objects but that requires rewriting this to do the query on those, not on
|
|
the wallets
|
|
'''
|
|
manywallets = Wallet.objects.all() # NB all of them
|
|
# manywallets = Wallet.objects.all().prefetch_related('singlescan') fails as the link is defined on 'singlescan' not on 'wallet'
|
|
expeditions = Expedition.objects.all()
|
|
return render(request, 'manywallets.html', { 'manywallets':manywallets, 'settings': settings, 'expeditions': expeditions })
|
|
|