mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-25 00:31:55 +00:00
fix directory for uploaded cave description photos
This commit is contained in:
parent
f5f3adf7da
commit
7908257d63
@ -46,7 +46,65 @@ todo = """
|
||||
own directory 16xx/NNN/ even if they have no images to put in it.
|
||||
"""
|
||||
|
||||
# def cavepagefwd(request, karea=None, subpath=None):
|
||||
# """archaic, just send to the caves list page
|
||||
# """
|
||||
# return redirect("/caves")
|
||||
|
||||
def get_cave_from_slug(caveslug):
|
||||
"""This is the old way of doing it, usingt eh CaveSlug intermediate object which does
|
||||
the many:many relationship between slugs and caves - whcih we don't do (and never did in practice)
|
||||
"""
|
||||
caves = []
|
||||
|
||||
print(f"get_cave_from_slug(): {caveslug} ...")
|
||||
areacode = caveslug[:4] # e.g. 1623
|
||||
id = caveslug[5:] # e.g. 161 or 2023-MM-02
|
||||
thisarea = Cave.objects.filter(areacode=areacode)
|
||||
|
||||
caves_k = thisarea.filter(kataster_number=id)
|
||||
if len(caves_k) == 1:
|
||||
caves.append(caves_k[0])
|
||||
print(f"get_cave_from_slug(): {caves_k=} {len(caves_k)=}")
|
||||
|
||||
caves_id = thisarea.filter(unofficial_number=id)
|
||||
if len(caves_id) == 1:
|
||||
caves.append(caves_id[0])
|
||||
print(f"get_cave_from_slug(): {caves_id=} {len(caves_id)=}")
|
||||
|
||||
if len(caves) > 1:
|
||||
print(f"get_cave_from_slug(): {caveslug} More than 1 \n{caves}")
|
||||
if len(caves) <1:
|
||||
print(f"get_cave_from_slug(): {caveslug} Nowt found..")
|
||||
cave = caves[0]
|
||||
print(f"get_cave_from_slug(): {caveslug} FOUND {cave}")
|
||||
|
||||
try:
|
||||
cave_zero = Cave.objects.get(caveslug__slug=caveslug)
|
||||
print(f"Getting cave from '{caveslug}'")
|
||||
if cave_zero != cave:
|
||||
print(f"get_cave_from_slug(): {caveslug} BAD DISCREPANCY {cave_zero=} {cave=}")
|
||||
else:
|
||||
print(f"get_cave_from_slug(): {caveslug} SUCCESS")
|
||||
|
||||
return cave_zero
|
||||
except:
|
||||
return None
|
||||
|
||||
def caveslugfwd(request, slug):
|
||||
"""This is ass backwards. It would be better style to have the slug-identified request be the master, and have
|
||||
other paths redirect to it, rather than what we have here.
|
||||
Pending a change where we remove cave.url as a field and have an explicit fixed convention instead.
|
||||
"""
|
||||
if not slug:
|
||||
message = f"Failed to find cave from identifier given: {slug}."
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
|
||||
Gcavelookup = GetCaveLookup()
|
||||
if slug in Gcavelookup:
|
||||
cave = Gcavelookup[slug]
|
||||
|
||||
return redirect(f"/{cave.url}")
|
||||
|
||||
|
||||
def getCaves(cave_id):
|
||||
@ -93,7 +151,7 @@ def pad5(x):
|
||||
|
||||
|
||||
def padnumber(x):
|
||||
return re.sub("\d+", pad5, x) # SyntaxWarning: invalid escape sequence '\d'
|
||||
return re.sub(r"\d+", pad5, x)
|
||||
|
||||
|
||||
def numericalcmp(x, y):
|
||||
@ -311,24 +369,7 @@ def rendercave(request, cave, slug, cave_id=""):
|
||||
) # crashes here with NoReverseMatch if url not set up for 'edit_cave' in urls.py
|
||||
return r
|
||||
|
||||
def cavepagefwd(request, karea=None, subpath=None):
|
||||
"""archaic, just send to the caves list page
|
||||
"""
|
||||
return redirect("/caves")
|
||||
|
||||
def caveslugfwd(request, slug):
|
||||
"""This is ass backwards. It would be better style to have the slug-identified request be the master, and have
|
||||
other paths redirect to it, rather than what we have here.
|
||||
Pending a change where we remove cave.url as a field and have an explicit fixed convention instead.
|
||||
"""
|
||||
if slug:
|
||||
Gcavelookup = GetCaveLookup()
|
||||
if slug in Gcavelookup:
|
||||
cave = Gcavelookup[slug]
|
||||
else:
|
||||
message = f"Failed to find cave from identifier given: {slug}."
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
return redirect(f"/{cave.url}")
|
||||
|
||||
def cavepage(request, karea=None, subpath=None):
|
||||
"""Displays a cave description page
|
||||
@ -368,9 +409,7 @@ def cavepage(request, karea=None, subpath=None):
|
||||
subparts = parts[0].split(".")
|
||||
caveid = subparts[0]
|
||||
slug = f"{karea}-{caveid}"
|
||||
caves = Cave.objects.filter(caveslug__slug=slug)
|
||||
if len(caves) == 1:
|
||||
cave = caves[0]
|
||||
if cave:= get_cave_from_slug(slug): # walrus operator
|
||||
return redirect(f"/{cave.url}")
|
||||
else:
|
||||
return redirect(f"/caves")
|
||||
@ -410,31 +449,31 @@ def edit_cave(request, path="", slug=None):
|
||||
"""
|
||||
print(f"edit_cave(): {path=} {slug=}")
|
||||
message = ""
|
||||
if slug is not None:
|
||||
print(f"{slug=}")
|
||||
try:
|
||||
cave = Cave.objects.get(caveslug__slug=slug)
|
||||
except:
|
||||
return render(request, "errors/badslug.html", {"badslug": f"{slug} - from edit_cave()"})
|
||||
if slug is None:
|
||||
cave = Cave() # create a New Cave
|
||||
else:
|
||||
cave = Cave()
|
||||
print(f"{slug=}")
|
||||
if not (cave:= get_cave_from_slug(slug)): # walrus operator
|
||||
return render(request, "errors/badslug.html", {"badslug": f"for cave {caveslug} - from edit_cave()"})
|
||||
|
||||
if request.POST:
|
||||
form = CaveForm(request.POST, instance=cave)
|
||||
#ceFormSet = CaveAndEntranceFormSet(request.POST)
|
||||
if form.is_valid(): # and ceFormSet.is_valid():
|
||||
# print(f'! POST is valid. {cave}')
|
||||
print(f'edit_cave(): POST is valid. Editing {cave}')
|
||||
cave = form.save(commit=False)
|
||||
print(cave)
|
||||
# print(cave)
|
||||
if not cave.filename:
|
||||
cave.filename = cave.areacode + "-" + cave.number() + ".html"
|
||||
if not cave.url:
|
||||
cave.url = cave.areacode + "/" + cave.number()
|
||||
cave.save()
|
||||
form.save_m2m()
|
||||
form.save_m2m() # this does the many-to-many relationship saving between caves and entrances
|
||||
if slug is None:
|
||||
# it is not visible on the form so it always will be None
|
||||
slug = f"{cave.areacode}-{cave.number()}"
|
||||
cs = CaveSlug(cave=cave, slug=slug, primary=True)
|
||||
print(f"edit_cave(): New CaveSlug saved {slug}")
|
||||
cs.save()
|
||||
#ceinsts = ceFormSet.save(commit=False)
|
||||
#for ceinst in ceinsts:
|
||||
@ -450,6 +489,8 @@ def edit_cave(request, path="", slug=None):
|
||||
except subprocess.SubprocessError:
|
||||
message = f"CANNOT git on server for this file {cave.filename}. Edits may not be committed.\nAsk a nerd to fix this."
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
except:
|
||||
raise
|
||||
if cave.entrances().count() > 0:
|
||||
return HttpResponseRedirect("/" + cave.url)
|
||||
else:
|
||||
@ -458,8 +499,8 @@ def edit_cave(request, path="", slug=None):
|
||||
else:
|
||||
if slug is not None:
|
||||
# re-read cave data from file.
|
||||
#print(f"edit_cave(): {cave=} {cave.filename=}")
|
||||
#print(f"edit_cave(): {cave.slug()=}")
|
||||
print(f"edit_cave(): {cave=} {cave.filename=}")
|
||||
print(f"edit_cave(): {cave.slug()=}")
|
||||
if cave.filename:
|
||||
try:
|
||||
read_cave(cave.filename, cave=cave)
|
||||
@ -473,6 +514,7 @@ def edit_cave(request, path="", slug=None):
|
||||
form = CaveForm()
|
||||
#ceFormSet = CaveAndEntranceFormSet(queryset=CaveAndEntrance.objects.none())
|
||||
|
||||
print(f"edit_cave(): returning render()")
|
||||
return render(
|
||||
request,
|
||||
"editcave.html",
|
||||
@ -486,6 +528,7 @@ def edit_cave(request, path="", slug=None):
|
||||
)
|
||||
|
||||
|
||||
|
||||
@login_required_if_public
|
||||
def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
"""This is the form that edits the entrance data for a single entrance and writes out
|
||||
@ -497,6 +540,9 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
|
||||
It does save the data into into the database directly, not by parsing the file.
|
||||
|
||||
'path' comes from the urls.py regex but is usually empty (!)
|
||||
So we make the proper path for storing the images ourselves.
|
||||
|
||||
GET RID of all this entranceletter stuff. Far too overcomplexified.
|
||||
We don't need it. Just the entrance slug is fine, then check uniqueness.
|
||||
"""
|
||||
@ -526,9 +572,7 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
nextletter = chr(ord(letter)+1)
|
||||
return check_new_slugname_ok(slug, nextletter)
|
||||
|
||||
try:
|
||||
cave = Cave.objects.get(caveslug__slug=caveslug)
|
||||
except:
|
||||
if not (cave:= get_cave_from_slug(caveslug)): # walrus operator
|
||||
return render(request, "errors/badslug.html", {"badslug": f"for cave {caveslug} - from edit_entrance()"})
|
||||
|
||||
if entslug:
|
||||
@ -541,7 +585,7 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
entrance = None
|
||||
|
||||
if entslug:
|
||||
print(f"{caveslug=} {entslug=} {path=} number of ents:{cave.entrances().count()}")
|
||||
print(f"Edit Entrance {caveslug=} {entslug=} {path=} number of ents:{cave.entrances().count()}")
|
||||
caveAndEntrance = CaveAndEntrance.objects.get(entrance=entrance, cave=cave)
|
||||
entlettereditable = False
|
||||
else:
|
||||
@ -557,6 +601,11 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
print(f"{entlettereditable=}")
|
||||
# if the entletter is not editable, then the entletterform does not appear and so is always invalid.
|
||||
|
||||
print(f"{caveslug=}")
|
||||
print(f"{cave=}")
|
||||
imgpath = Path(path) / cave.areacode / cave.number()
|
||||
print(f"Edit Entrance {imgpath=}")
|
||||
|
||||
if request.POST:
|
||||
print(f"POST Online edit of entrance: '{entrance}' where {cave=}")
|
||||
entform = EntranceForm(request.POST, instance=entrance)
|
||||
@ -683,7 +732,7 @@ def edit_entrance(request, path="", caveslug=None, entslug=None):
|
||||
"entletter": entletter,
|
||||
"entletterform": entletterform, # is unset if not being used
|
||||
"entlettereditable": entlettereditable,
|
||||
"path": path + "/", # used for saving images if attached
|
||||
"path": str(imgpath) + "/", # used for saving images if attached
|
||||
},
|
||||
)
|
||||
|
||||
@ -719,9 +768,7 @@ def caveslist(request):
|
||||
{"caves": caves, "year": current_expo()},
|
||||
)
|
||||
def get_entrances(request, caveslug):
|
||||
try:
|
||||
cave = Cave.objects.get(caveslug__slug=caveslug)
|
||||
except:
|
||||
if not (cave:= get_cave_from_slug(caveslug)): # walrus operator
|
||||
return render(request, "errors/badslug.html", {"badslug": f"{caveslug} - from get_entrances()"})
|
||||
return render(
|
||||
request, "options.html", {"year": current_expo(), "items": [(e.entrance.slug(), e.entrance.slug()) for e in cave.entrances()]}
|
||||
@ -733,9 +780,7 @@ def caveQMs(request, slug, open=False):
|
||||
relies on the template to find all the QMs for the cave specified in the slug, e.g. '1623-161'
|
||||
Now working in July 2022
|
||||
"""
|
||||
try:
|
||||
cave = Cave.objects.get(caveslug__slug=slug)
|
||||
except:
|
||||
if not (cave:= get_cave_from_slug(caveslug)): # walrus operator
|
||||
return render(request, "errors/badslug.html", {"badslug": f"{slug} - from caveQMs()"})
|
||||
|
||||
if cave.non_public and settings.PUBLIC_SITE and not request.user.is_authenticated:
|
||||
|
@ -26,6 +26,11 @@ THUMBNAIL_HEIGHT = 200
|
||||
|
||||
It uses a lot of opinionated Django default magic, none of which I am familiar with.
|
||||
Philip
|
||||
|
||||
The function image_selector() is only called from a template file doing a popup input form,
|
||||
but it stores files directly in expoweb/i /l /t instead of in
|
||||
/expoweb/1623/2018-MS-01/i , /l, /t
|
||||
so ALL new caves have photos in the smae place, which makes the default upload EXTREMELY CONFUSING
|
||||
"""
|
||||
|
||||
def get_dir(path):
|
||||
@ -38,7 +43,10 @@ def get_dir(path):
|
||||
|
||||
|
||||
def image_selector(request, path):
|
||||
"""Returns available images"""
|
||||
"""Returns available images
|
||||
called from
|
||||
templates/html_editor_scripts_css.html: $('#image_popup_content').load("{% url 'image_selector' path %}" + path, function() {
|
||||
"""
|
||||
directory = get_dir(path)
|
||||
print(f" - image selector {directory=} {path=}")
|
||||
thumbnailspath = Path(settings.EXPOWEB) / directory / "t"
|
||||
@ -89,15 +97,23 @@ def reorient_image(img, exif_dict):
|
||||
def new_image_form(request, path):
|
||||
"""Manages a form to upload new images"""
|
||||
directory = get_dir(path)
|
||||
print(f"new_image_form(): {directory=} {path=}")
|
||||
if request.method == "POST":
|
||||
print(f"new_image_form(): POST ")
|
||||
form = NewWebImageForm(request.POST, request.FILES, directory=directory)
|
||||
if form.is_valid():
|
||||
print(f"new_image_form(): form is valid ")
|
||||
print(f"new_image_form(): files: {request.FILES["file_"]}")
|
||||
f = request.FILES["file_"]
|
||||
binary_data = io.BytesIO()
|
||||
for chunk in f.chunks():
|
||||
binary_data.write(chunk)
|
||||
print(f"new_image_form(): binary chnks written")
|
||||
i = Image.open(binary_data)
|
||||
print(f"new_image_form(): {i=}")
|
||||
if "exif" in i.info:
|
||||
print(f"new_image_form(): exif: {i=}")
|
||||
|
||||
exif_dict = piexif.load(i.info["exif"])
|
||||
i = reorient_image(i, exif_dict)
|
||||
exif_dict['Exif'][41729] = b'1'
|
||||
@ -109,13 +125,21 @@ def new_image_form(request, path):
|
||||
else:
|
||||
exif = None
|
||||
|
||||
print(f"new_image_form(): No exif problems")
|
||||
width, height = i.size
|
||||
print(f"new_image_form(): {i.size=}")
|
||||
if width > MAX_IMAGE_WIDTH or height > MAX_IMAGE_HEIGHT:
|
||||
print(f"new_image_form(): rescaling ")
|
||||
scale = max(width / MAX_IMAGE_WIDTH, height / MAX_IMAGE_HEIGHT)
|
||||
i = i.resize((int(width / scale), int(height / scale)), Image.ANTIALIAS)
|
||||
tscale = max(width / THUMBNAIL_WIDTH, height / THUMBNAIL_HEIGHT)
|
||||
thumbnail = i.resize((int(width / tscale), int(height / tscale)), Image.ANTIALIAS)
|
||||
print(f"new_image_form(): rescaling {scale=}")
|
||||
try:
|
||||
i = i.resize((int(width / scale), int(height / scale)), Image.LANCZOS)
|
||||
except Exception as e:
|
||||
print(f"new_image_form(): rescaling exception: {e} ")
|
||||
|
||||
print(f"new_image_form(): rescaled ")
|
||||
tscale = max(width / THUMBNAIL_WIDTH, height / THUMBNAIL_HEIGHT)
|
||||
thumbnail = i.resize((int(width / tscale), int(height / tscale)), Image.LANCZOS)
|
||||
ib = io.BytesIO()
|
||||
i = i.convert('RGB')
|
||||
i.save(ib, format="jpeg", quality = 75)
|
||||
@ -123,6 +147,7 @@ def new_image_form(request, path):
|
||||
thumbnail = thumbnail.convert('RGB')
|
||||
thumbnail.save(tb, format="jpeg", quality = 70)
|
||||
image_rel_path, thumb_rel_path, desc_rel_path = form.get_rel_paths()
|
||||
print(f"new_image_form(): \n {image_rel_path=}\n {thumb_rel_path=}\n {desc_rel_path=}")
|
||||
image_page_template = loader.get_template("image_page_template.html") # this is the .html file in the /l/ folder
|
||||
image_page = image_page_template.render(
|
||||
{
|
||||
@ -149,14 +174,21 @@ def new_image_form(request, path):
|
||||
f"{change_message} - online adding of an image",
|
||||
)
|
||||
except WriteAndCommitError as e:
|
||||
print(f"new_image_form(): WriteAndCommitError: {e.message}")
|
||||
return JsonResponse({"error": e.message})
|
||||
except Exception as e:
|
||||
print(f"new_image_form(): EXCEPTION: {e.message}")
|
||||
return JsonResponse({"error": e.message})
|
||||
|
||||
linked_image_template = loader.get_template("linked_image_template.html")
|
||||
html_snippet = linked_image_template.render(
|
||||
{"thumbnail_url": f"/{thumb_rel_path}", "page_url": f"/{desc_rel_path}"}, request
|
||||
)
|
||||
return JsonResponse({"html": html_snippet})
|
||||
else:
|
||||
print(f"new_image_form(): not POST ")
|
||||
form = NewWebImageForm(directory=directory)
|
||||
print(f"new_image_form(): POST and not POST ")
|
||||
template = loader.get_template("new_image_form.html")
|
||||
htmlform = template.render({"form": form, "path": path}, request)
|
||||
return JsonResponse({"form": htmlform})
|
||||
|
@ -16,8 +16,8 @@ the form documented at
|
||||
<br>
|
||||
|
||||
<cave>
|
||||
<non_public>{{ cave.non_public }}</non_public>{% for slug in cave.caveslug_set.all %}<!-- 'False' or 'True'. True if the cave should only be visible to logged-in users. Caves are normally public, so enter 'False' unless you know otherwise. -->
|
||||
<!--<caveslug>{{ slug.slug|default_if_none:"1623-000"|safe }}</caveslug>{% endfor %}--> <!-- Ignored. No longer required, we use the filename instead e.g. 1623-315 for 1623-315.html -->
|
||||
<non_public>{{ cave.non_public }}</non_public><!-- 'False' or 'True'. True if the cave should only be visible to logged-in users. Caves are normally public, so enter 'False' unless you know otherwise. -->
|
||||
<!--<caveslug>{{ slug.slug|default_if_none:"1623-000"|safe }}</caveslug>--> <!-- Ignored. No longer required, we use the filename instead e.g. 1623-315 for 1623-315.html -->
|
||||
<official_name>{{ cave.official_name|default_if_none:""|safe }}</official_name><!-- Name of the cave (normally in German) Use ü for u+Umlaut and ö for o+umlaut eg Höhle for Hohle and Glück for Gluck-->
|
||||
<area>{{cave.areacode |safe }}</area><!-- e.g. "1623" -->
|
||||
<kataster_code>{{ cave.kataster_code|default_if_none:"-"|safe }}</kataster_code><!-- 'length-or-depth/type exploration'
|
||||
|
8
urls.py
8
urls.py
@ -7,7 +7,7 @@ from django.conf.urls.static import static
|
||||
from troggle.core.views import statistics, survex
|
||||
from troggle.core.views.auth import expologin, expologout
|
||||
from troggle.core.views.caves import (cave3d, caveindex, entranceindex, caveslist,
|
||||
cavepage, caveslugfwd, cavepagefwd, caveQMs, edit_cave, cave_debug,
|
||||
cavepage, caveslugfwd, caveQMs, edit_cave, cave_debug,
|
||||
edit_entrance, get_entrances, qm, expo_kml, expo_kmz)
|
||||
from troggle.core.views.drawings import dwgallfiles, dwgfilesingle
|
||||
from troggle.core.views.editor_helpers import image_selector, new_image_form
|
||||
@ -173,9 +173,9 @@ trogglepatterns = [
|
||||
# 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
|
||||
|
||||
# These re-enable archaic URLs which are in old web pages which are still public on other servers
|
||||
path('smkridge/<path:subpath>', cavepagefwd, {'karea': "1623"}, name="cavepagefwd"),
|
||||
path('expo/smkridge/<path:subpath>', cavepagefwd, {'karea': "1623"}, name="cavepagefwd"),
|
||||
# These re-enable archaic URLs which are in old web pages which may still be public on other servers - old
|
||||
# path('smkridge/<path:subpath>', cavepagefwd, {'karea': "1623"}, name="cavepagefwd"),
|
||||
# path('expo/smkridge/<path:subpath>', cavepagefwd, {'karea': "1623"}, name="cavepagefwd"),
|
||||
|
||||
# Archaic, kept. This /expo/ prefix only works for expoweb HTML pages not troggle pages
|
||||
path('expo/<path:path>', expopage, name="expopage"),
|
||||
|
Loading…
Reference in New Issue
Block a user