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 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. ''' def populatewallet(w): '''Copy survex data here just for display, not permanently ''' # {% for personrole in wallet.survexblock.survexpersonrole_set.all %} # {% if personrole.personexpedition %} # {{personrole.personname}} # {% else %} # {{personrole.personname}} # {% endif %} # {% endfor %} 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 def caveifywallet(w): 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.cave = b.survexfile.cave # just gets the last one, randomly 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 try: if last_name: p = Person.objects.get(fullname= f'{first_name} {last_name}') else: # speciall 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}"'}) #personyear = GetPersonExpeditionNameLookup(expedition).get(tripperson.lower()) earliest = datetime.datetime.now().date() manywallets = [] wallets = Wallet.objects.all() for w in wallets: w.persons = w.people() # ephemeral attribute for web page # check if there is a json if not w.get_json(): populatewallet(w) else: wp = w.people() if not wp: # an -empty list populatewallet(w) else: if len(wp) == 1: nobody = wp[0].lower() if nobody == 'unknown' or nobody == 'nobody' or nobody == ' ': populatewallet(w) if p.fullname in w.persons: #found person manywallets.append(w) if not w.date(): datewallet(w, earliest) c = w.cave() if not c: caveifywallet(w) return render(request, 'personwallets.html', { 'manywallets':manywallets, 'settings': settings, 'person': p}) def walletslistyear(request, year): '''Page which displays a list of all the wallets in a specific year ''' 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'}) earliest = datetime.datetime.now().date() manywallets = [] wallets = Wallet.objects.all() for w in wallets: if year == w.year(): print(w.year(), w) manywallets.append(w) else: continue wp = w.people() if not wp: # an -empty list populatewallet(w) else: if len(wp) == 1: nobody = wp[0].lower() if nobody == 'unknown' or nobody == 'nobody' or nobody == ' ': populatewallet(w) if not w.date(): datewallet(w, earliest) c = w.cave() if not c: caveifywallet(w) return render(request, 'yearwallets.html', { 'manywallets':manywallets, 'settings': settings, 'year': year}) 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}) earliest = datetime.datetime.now().date() # remove duplication. SOrting is done in the template wallets = set(Wallet.objects.filter(survexblock__survexfile__cave=cave)) # NB a filtered set manywallets = list(wallets) for w in manywallets: wp = w.people() if not wp: # an -empty list populatewallet(w) else: if len(wp) == 1: nobody = wp[0].lower() if nobody == 'unknown' or nobody == 'nobody' or nobody == ' ': populatewallet(w) if not w.date(): datewallet(w, earliest) c = w.cave() if not c: caveifywallet(w) return render(request, 'cavewallets.html', { 'manywallets':manywallets, 'settings': settings, 'cave': cave}) 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 walletindex(request, path): '''All years: special 'wallet' for scanned index pages ''' # print([ s.walletname for s in Wallet.objects.all() ]) print(f'! - walletindex path:{path}') try: wallet = Wallet.objects.get(walletname=urlunquote(path)) return render(request, 'walletindex.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) print(" - scansingle {}:{}:{}:".format(path, file, getmimetype(file))) return HttpResponse(content=open(singlescan.ffile,"rb"), content_type=getmimetype(file)) # any type of image except: message = f'Scan folder or scan item error or not found \'{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' return render(request, 'manywallets.html', { 'manywallets':manywallets, 'settings': settings })