forked from expo/troggle
hack wallet scan rename job
This commit is contained in:
parent
5f07f234ef
commit
89c1c65340
@ -14,7 +14,9 @@ import re
|
||||
|
||||
"""These are all the class-based Forms used by troggle.
|
||||
There are other, simpler, upload forms in view/uploads.py
|
||||
Some are not used and need renovating or destroying.
|
||||
|
||||
class-based forms are quicker to set up (for Django experts) but
|
||||
are more difficult to maintain by non-Django experts.
|
||||
"""
|
||||
|
||||
todo = """
|
||||
|
@ -3,7 +3,7 @@ from pathlib import Path
|
||||
|
||||
from django import forms
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
from django.shortcuts import render
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
import settings
|
||||
from troggle.core.models.survex import DrawingFile
|
||||
@ -13,6 +13,8 @@ from troggle.core.models.survex import DrawingFile
|
||||
from .auth import login_required_if_public
|
||||
|
||||
"""File upload 'views'
|
||||
Note that there are other file upload forms in views/wallet_edit.py
|
||||
and that core/forms.py contains Django class-based forms for caves and entrances.
|
||||
"""
|
||||
|
||||
todo = """
|
||||
@ -25,12 +27,14 @@ todo = """
|
||||
Need to validate it as being a valid GPX file using an XML parser, not a dubious script or hack
|
||||
|
||||
- Validate Tunnel & Therion files using an XML parser in dwgupload(). Though Julian says
|
||||
tunnel is only mostly correct XML
|
||||
tunnel is only mostly correct XML, and it does fail at least one XML parser.
|
||||
|
||||
- parse the uploaded drawing file for links to wallets and scan files as done
|
||||
in parsers/drawings.py
|
||||
|
||||
- Enable folder creation in dwguploads or as a separate form
|
||||
|
||||
- Enable file rename on expofiles, particularly in /surveyscans/ (aka wallets)
|
||||
"""
|
||||
|
||||
class FilesForm(forms.Form): # not a model-form, just a form-form
|
||||
@ -42,7 +46,64 @@ class FilesRenameForm(forms.Form): # not a model-form, just a form-form
|
||||
|
||||
class TextForm(forms.Form): # not a model-form, just a form-form
|
||||
photographer = forms.CharField(strip=True)
|
||||
|
||||
class ExpofileRenameForm(forms.Form): # not a model-form, just a form-form
|
||||
renameto = forms.CharField(strip=True, required=False)
|
||||
|
||||
@login_required_if_public
|
||||
def expofilerename(request, filepath):
|
||||
"""Rename any single file in /expofiles/ - eventually.
|
||||
Currently this just does files within wallets i.e. in /surveyscans/
|
||||
and it returns control to the original wallet edit page
|
||||
"""
|
||||
if filepath:
|
||||
actualpath = Path(settings.EXPOFILES) / Path(filepath)
|
||||
else:
|
||||
message = f'\n File to rename not specified "{filepath}"'
|
||||
print(message)
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
|
||||
if not actualpath.is_file():
|
||||
message = f'\n File not found when attempting rename "{filepath}"'
|
||||
print(message)
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
else:
|
||||
filename = Path(filepath).name
|
||||
folder = Path(actualpath).parent
|
||||
|
||||
if not actualpath.is_relative_to(Path(settings.SCANS_ROOT)):
|
||||
message = f'\n Can only do rename within wallets (expofiles/surveyscans/) currently, sorry. "{actualpath}" '
|
||||
print(message)
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
|
||||
|
||||
if request.method == "POST":
|
||||
form = ExpofileRenameForm(request.POST)
|
||||
if form.is_valid():
|
||||
renameto = request.POST["renameto"]
|
||||
|
||||
if (folder / renameto).is_file():
|
||||
message = f'\n Cannot rename to an existing file. "{filename}" -> "{(folder / renameto)}"'
|
||||
print(message)
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
else:
|
||||
actualpath.rename((folder / renameto))
|
||||
message = f'\n RENAMED "{filename}" -> "{(folder / renameto)}"'
|
||||
print(message)
|
||||
return redirect('/survey_scans/2023%252314/')
|
||||
|
||||
else:
|
||||
form = ExpofileRenameForm()
|
||||
return render(
|
||||
request,
|
||||
"renameform.html",
|
||||
{
|
||||
"form": form,
|
||||
"filepath": filepath,
|
||||
"filename": filename,
|
||||
},
|
||||
)
|
||||
|
||||
@login_required_if_public
|
||||
def photoupload(request, folder=None):
|
||||
"""Upload photo image files into /expofiles/photos/<year>/<photographer>/
|
||||
@ -55,6 +116,8 @@ def photoupload(request, folder=None):
|
||||
be renamed to something useful before starting the upload.
|
||||
Unfortunately this only works when uploading one file at at time ,
|
||||
inevitable once you think about it.
|
||||
|
||||
Pending generic file renaming capability more generally.
|
||||
"""
|
||||
year = settings.PHOTOS_YEAR
|
||||
filesaved = False
|
||||
@ -186,7 +249,8 @@ def dwgupload(request, folder=None, gitdisable="no"):
|
||||
This does NOT use a Django model linked to a Django form. Just a simple Django form.
|
||||
You will find the Django documentation on forms very confusing, This is simpler.
|
||||
|
||||
We could validate the uploaded files as being a valid files using an XML parser, not a dubious script or hack
|
||||
We could validate the uploaded files as being a valid files using an XML parser, not a dubious script or hack,
|
||||
but this won't work on Tunnel files as Tunnel does not produce exactly valid xml
|
||||
|
||||
We use get_or_create instead of simply creating a new object in case someone uploads the same file
|
||||
several times in one session, and expects them to be overwritten in the database. Although
|
||||
|
@ -272,10 +272,14 @@ def walletedit(request, path=None):
|
||||
|
||||
This does NOT use a Django model linked to a Django form. Just a simple Django form.
|
||||
You will find the Django documentation on forms very confusing,
|
||||
as it covers many very differnet things we do not need. This is simpler.
|
||||
as it covers many very different things we do not need. This is simpler.
|
||||
(See also view/uploads.py for other simpler forms, as opposed to core/forms.py
|
||||
which contains a couple of Django class-based forms.)
|
||||
|
||||
This subsumes much of the code which was in the pre-2022 non-troggle wallets.py script
|
||||
and so this function is very long indeed and needs refactoring.
|
||||
|
||||
Much of the logic used here lives in the Class functions for Wallet.
|
||||
|
||||
REWRITE bits using the ticklist, dateify, caveify, populate etc utility functions in core.view.scans.py
|
||||
"""
|
||||
|
@ -1781,7 +1781,7 @@ class LoadingSurvex:
|
||||
|
||||
# this is a python generator idiom.
|
||||
# see https://realpython.com/introduction-to-python-generators/
|
||||
# this is the first use of generators in troggle (Oct.2022) and save 21 MB of memory
|
||||
# this is the first use of generators in troggle (Oct.2022) and saves 21 MB of memory
|
||||
with open(collatefilename, "r") as fcollate:
|
||||
for svxline in fcollate:
|
||||
self.lineno += 1
|
||||
@ -1789,22 +1789,22 @@ class LoadingSurvex:
|
||||
if comment:
|
||||
# this catches the ;|*include NEWFILE and ;|*edulcni ENDOFFILE lines too
|
||||
self.LoadSurvexComment(survexblock, comment)
|
||||
else:
|
||||
# detect a merge failure inserted by version control
|
||||
mfail = self.rx_badmerge.match(sline)
|
||||
if mfail:
|
||||
message = f"\n ! - ERROR version control merge failure\n - '{sline}'\n"
|
||||
message = (
|
||||
message + f" - line {self.lineno} in {blkid} in {survexblock}\n - NERD++ needed to fix it"
|
||||
)
|
||||
print(message)
|
||||
print(message, file=sys.stderr)
|
||||
stash_data_issue(parser="survex", message=message)
|
||||
continue # skip this line
|
||||
|
||||
if not sline:
|
||||
continue # skip blank lines
|
||||
|
||||
# detect a merge failure inserted by version control
|
||||
mfail = self.rx_badmerge.match(sline)
|
||||
if mfail:
|
||||
message = f"\n ! - ERROR version control merge failure\n - '{sline}'\n"
|
||||
message = (
|
||||
message + f" - line {self.lineno} in {blkid} in {survexblock}\n - NERD++ needed to fix it"
|
||||
)
|
||||
print(message)
|
||||
print(message, file=sys.stderr)
|
||||
stash_data_issue(parser="survex", message=message)
|
||||
continue # skip this line
|
||||
|
||||
# detect a star command
|
||||
star = self.rx_star.match(sline)
|
||||
if star:
|
||||
@ -1829,7 +1829,7 @@ class LoadingSurvex:
|
||||
mfail = self.rx_badmerge.match(svxline)
|
||||
if mfail:
|
||||
message = f"\n!! - ERROR version control merge failure\n - '{svxline}'\n"
|
||||
message = message + f" - in '{path}' at line {thissvxline}\n"
|
||||
message = message + f" - in '{path}' at line {self.lineno}\n"
|
||||
message = (
|
||||
message + f" - line {self.lineno} {survexblock}\n - Parsing aborted. NERD++ needed to fix it"
|
||||
)
|
||||
@ -1963,7 +1963,7 @@ class LoadingSurvex:
|
||||
stash_data_issue(parser="survex", message=message, url=None, sb=(path))
|
||||
return # skip this survex file and all things *included in it
|
||||
except:
|
||||
message = f" ! ERROR *include file '{path}' in '{survexblock}' has unexpected error on opening file. OMITTED!"
|
||||
message = f" ! ERROR *include file '{path}' in '{survexblock}' has unexpected error on opening or reading file. OMITTED!"
|
||||
print(message)
|
||||
print(message, file=sys.stderr)
|
||||
stash_data_issue(parser="survex", message=message, url=None, sb=(path))
|
||||
|
38
templates/renameform.html
Normal file
38
templates/renameform.html
Normal file
@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}File rename form{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>Rename "{{filename}}"</h2>
|
||||
<figure class=onleft>
|
||||
<img src="/expofiles/{{filepath|urlencode}}" width=150px>
|
||||
</figure>
|
||||
<div style = "max-width:95%; margin-left:8%; text-align: left; " >
|
||||
<form method ='post' >
|
||||
{% csrf_token %}
|
||||
<br>
|
||||
<input class="fancybutton2" style="padding: 0.5em 25px; margin-left: 110px "
|
||||
label = "Rename to" name = "renameto" id="renameto"
|
||||
pattern="[A-Za-z][A-Za-z0-9_-\.]*"/>
|
||||
<label
|
||||
style="padding: 0.5em 25px; margin-left: 110px"
|
||||
for="renameto">the new name for this file<br></label>
|
||||
<br><br><br>
|
||||
|
||||
<button class="fancybutton2" style="padding: 0.5em 25px; margin-left: 110px" type = "submit" value = "Upload" >
|
||||
Rename it
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<br /><br /><br />
|
||||
Full urlencoded path for this file <a href="/expofiles/{{filepath|urlencode}}"><em>{{filepath|urlencode}}</em></a>
|
||||
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
{% endblock %}
|
@ -72,7 +72,7 @@
|
||||
{% if not create %}
|
||||
<p>
|
||||
{% for f in files %}
|
||||
<a href="/expofiles/surveyscans/{{year}}/{{wallet|urlencode}}/{{f}}">{{ f}}</a><br />
|
||||
<a href="/expofilerename/surveyscans/{{year}}/{{wallet|urlencode}}/{{f}}">»</a> <a href="/expofiles/surveyscans/{{year}}/{{wallet|urlencode}}/{{f}}">{{ f}}</a><br />
|
||||
{% empty %}
|
||||
<p><No files in this wallet. >
|
||||
|
||||
|
5
urls.py
5
urls.py
@ -24,7 +24,7 @@ from troggle.core.views.other import (controlpanel, exportlogbook, frontpage,
|
||||
from troggle.core.views.prospect import prospecting
|
||||
from troggle.core.views.scans import (allscans, cavewallets, scansingle,
|
||||
walletslistperson, walletslistyear)
|
||||
from troggle.core.views.uploads import dwgupload, photoupload
|
||||
from troggle.core.views.uploads import dwgupload, photoupload, expofilerename
|
||||
from troggle.core.views.wallets_edit import walletedit
|
||||
"""This sets the actualurlpatterns[] and urlpatterns[] lists which django uses
|
||||
to resolve urls - in both directions as these are declarative.
|
||||
@ -110,6 +110,9 @@ trogglepatterns = [
|
||||
path('dwguploadnogit/', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing
|
||||
path('dwguploadnogit/<path:folder>', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing
|
||||
|
||||
# Renaming an uploaded file
|
||||
path('expofilerename/<path:filepath>', expofilerename, name='expofilerename'),
|
||||
|
||||
# setting LOGIN_URL = '/accounts/login/' is default.
|
||||
# NB setting url pattern name to 'login' instea dof 'expologin' with override Django, see https://docs.djangoproject.com/en/dev/topics/http/urls/#naming-url-patterns
|
||||
path('accounts/logout/', expologout, name='expologout'), # same as in django.contrib.auth.urls
|
||||
|
Loading…
Reference in New Issue
Block a user