From b65639df05d34221e546140b692f329b7f28404e Mon Sep 17 00:00:00 2001 From: Philip Sargent Date: Sun, 13 Mar 2022 01:01:00 +0000 Subject: [PATCH] Upload form for Photos --- core/TESTS/tests.py | 3 +- core/views/uploads.py | 83 +++++++++++++++++++++++++++++- media/css/trog3.css | 54 +++++++++++++++++++- templates/base.html | 1 + templates/photouploadform.html | 93 ++++++++++++++++++++++++++++++++++ urls.py | 10 ++-- 6 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 templates/photouploadform.html diff --git a/core/TESTS/tests.py b/core/TESTS/tests.py index 3bcebc4..98c85f4 100644 --- a/core/TESTS/tests.py +++ b/core/TESTS/tests.py @@ -153,7 +153,7 @@ class PageTests(TestCase): def test_expoweb_via_areaid(self): # the dispatcher takes a detour via the cave renering procedure for this - response = self.client.get('/1623/others/t/via201.jpg') + response = self.client.get('/guidebook/t/via201.jpg') self.assertEqual(response.status_code, 200) self.assertEqual(len(response.content), 6057) @@ -175,7 +175,6 @@ class PageTests(TestCase): phmatch = re.search(ph, content) self.assertIsNotNone(phmatch, "Failed to find expected text: '" + ph +"'") - def test_page_admin(self): # see the login page response = self.client.get('/admin/login/') diff --git a/core/views/uploads.py b/core/views/uploads.py index a052835..d227bda 100644 --- a/core/views/uploads.py +++ b/core/views/uploads.py @@ -12,6 +12,7 @@ from django.shortcuts import render from django.template import Context, loader from django.core.files.storage import FileSystemStorage, default_storage +#from troggle import settings from troggle.parsers.imports import import_caves, import_people, import_surveyscans from troggle.parsers.imports import import_logbooks, import_QMs, import_drawingsfiles, import_survex # from databaseReset import reinit_db # don't do this. databaseRest runs code *at import time* @@ -19,6 +20,7 @@ from troggle.core.models.troggle import Expedition, Person, PersonExpedition from troggle.core.models.caves import LogbookEntry, QM, Cave, PersonTrip from troggle.core.models.survex import DrawingFile from .auth import login_required_if_public +#from django.views.decorators.csrf import ensure_csrf_cookie, csrf_exempt '''File upload 'views' ''' @@ -42,6 +44,9 @@ todo = ''' class FilesForm(forms.Form): # not a model-form, just a form-form uploadfiles = forms.FileField() +class TextForm(forms.Form): # not a model-form, just a form-form + photographer = forms.CharField(strip=True) + @login_required_if_public def scanupload(request, wallet=None): '''Upload scanned image files into a wallet on /expofiles @@ -77,9 +82,11 @@ def scanupload(request, wallet=None): dirpath = Path(settings.SURVEY_SCANS, year, wallet) form = FilesForm() - + if request.method == 'POST': form = FilesForm(request.POST,request.FILES) + print(f'! - FilesForm POSTED') + if form.is_valid(): f = request.FILES["uploadfiles"] multiple = request.FILES.getlist('uploadfiles') @@ -115,6 +122,80 @@ def scanupload(request, wallet=None): return render(request, 'scanuploadform.html', {'form': form, 'wallet': wallet, **context, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved}) +@login_required_if_public +def photoupload(request, folder=None): + '''Upload photo image files into /expofiles/photos/// + 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. + ''' + year = settings.PHOTOS_YEAR + filesaved = False + actual_saved = [] + + context = {'year': year, 'placeholder': "AnathemaDevice"} + + yearpath = Path(settings.PHOTOS_ROOT, year) + + if folder == str(year) or folder == str(year) +"/": + folder = None + + if folder is None: + folder = "" # improve this later + dirpath = Path(settings.PHOTOS_ROOT, year) + urlfile = f'/expofiles/photos/{year}' + urldir = f'/photoupload/{year}' + else: # it will contain the year as well as the photographer + dirpath = Path(settings.PHOTOS_ROOT, folder) + if dirpath.is_dir(): + urlfile = f'/expofiles/photos/{folder}' + urldir = Path('/photoupload') / folder + else: + folder = "" # improve this later + dirpath = Path(settings.PHOTOS_ROOT, year) + urlfile = f'/expofiles/photos/{year}' + urldir = f'/photoupload/{year}' + + + form = FilesForm() + formd = TextForm() + + if request.method == 'POST': + if "photographer" in request.POST: + formd = TextForm(request.POST) + if formd.is_valid(): + newphotographer = request.POST["photographer"] + (yearpath / newphotographer).mkdir(exist_ok=True) + else: + form = FilesForm(request.POST,request.FILES) + if form.is_valid(): + f = request.FILES["uploadfiles"] + multiple = request.FILES.getlist('uploadfiles') + fs = FileSystemStorage(dirpath) + + actual_saved = [] + if multiple: + for f in multiple: + actual_saved.append( fs.save(f.name, content=f) ) + filesaved = True + files = [] + dirs = [] + try: + for f in dirpath.iterdir(): + if f.is_dir(): + dirs.append(f.name) + if f.is_file(): + files.append(f.name) + except FileNotFoundError: + files.append('(no folder yet - would be created)') + if len(files) >0 : + files = sorted(files) + + if dirs: + dirs = sorted(dirs) + + return render(request, 'photouploadform.html', + {'form': form, **context, 'urlfile': urlfile, 'urldir': urldir,'folder': folder, 'files': files, 'dirs': dirs, 'filesaved': filesaved, 'actual_saved': actual_saved}) + @login_required_if_public def dwgupload(request, folder=None, gitdisable='no'): '''Upload DRAWING files (tunnel or therion) into the upload folder in :drawings diff --git a/media/css/trog3.css b/media/css/trog3.css index a3e622a..3da931a 100644 --- a/media/css/trog3.css +++ b/media/css/trog3.css @@ -427,7 +427,7 @@ div#difflistajax background-color: #dfffdf; border: thin green solid; } - +/* Using in DrawingsUpload and ScanUpload*/ .fancybutton { color: #ffffff; font: 18px Georgia, "Times New Roman", Times, serif; @@ -479,6 +479,58 @@ div#difflistajax background: linear-gradient(bottom, #39b2e5, #6083BF); } +/* Used in PhotoUpload and GPSlog upload */ +.fancybutton2 { + color: #ffffff; + font: 18px Georgia, "Times New Roman", Times, serif; + letter-spacing: 1px; + + text-shadow: 0 1px 1px #000000; + + #display: block; +/* margin: auto; */ + font-size: 1.2em; + line-height: 1.25em; + + padding: 7px 25px; + cursor: pointer; + position: static; + background: #9ff; + border: 1px solid #60AABF; +/* -moz-border-radius: 20px; + -webkit-border-radius: 20px; + -khtml-border-radius: 20px;*/ + border-radius: 20px; + /* + -webkit-box-shadow: rgba(0, 0, 0, .25) 0 1px 1px; + -moz-box-shadow: rgba(0, 0, 0, .25) 0 1px 1px; + -o-box-shadow: rgba(0, 0, 0, .25) 0 1px 1px;*/ + box-shadow: rgba(0, 0, 0, .25) 0 1px 1px; + background: #9ff; + background: -webkit-gradient(linear, left top, left bottom, from(#9ff), to(#6083fF)); + background: -moz-linear-gradient(top, #9ff, #6083fF); + background: -o-linear-gradient(top, #9ff, #6083fF); + background: linear-gradient(top, #9ff, #6083fF); + } + +.fancybutton2:hover, +.fancybutton2:focus { + cursor: pointer; + border-color: blue; +/* -webkit-box-shadow: aqua 0 0 8px; + -moz-box-shadow: aqua 0 0 8px; + -o-box-shadow: aqua 0 0 8px; */ + box-shadow: aqua 0 0 8px; +} + +.fancybutton2:active { + background: #39e5b2; +/* background: -webkit-gradient(linear, left bottom, left top, from(#39e5b2), to(#6083BF)); + background: -moz-linear-gradient(bottom, #39e5b2, #6083BF); + background: -o-linear-gradient(bottom, #39e5b2, #6083BF); */ + background: linear-gradient(bottom, #9ff, #6083BF); +} + /* For the Scan upload form - to be used with a phone */ ::-webkit-file-upload-button { padding: 0.3em; diff --git a/templates/base.html b/templates/base.html index 5cb122d..e94db63 100644 --- a/templates/base.html +++ b/templates/base.html @@ -35,6 +35,7 @@ Upload Scans | Drawings | Upload Drawings | + Upload Photos | 290 (FGH) | 359 (Homecoming) |
diff --git a/templates/photouploadform.html b/templates/photouploadform.html new file mode 100644 index 0000000..0d6dddc --- /dev/null +++ b/templates/photouploadform.html @@ -0,0 +1,93 @@ +{% extends "base.html" %} + +{% block title %}Simple Fileupload (Photos){% endblock %} + +{% block content %} + + +{% if folder %} +

Upload photos into /photos/{{folder}}/

+{% else %} +

Upload photos into /photos/{{year}}/

+{% endif %} + + +
+
+ {% csrf_token %} +
+ +


+ +
+
+
+ {% if filesaved %} +

+ File(s) saved as
+ {% for f in actual_saved %} + {{f}}
+ {% endfor %} +

+ {% endif %} + + Files:
+ {% for f in files %} + {{f}}
+ {% empty %} +

<No files here> + {% endfor %} + + +

Photographer Directories:
+ {% if folder %} + [up]
+ {% endif %} + {% for f in dirs %} + /{{f}}/
+ {% empty %} +

<No subdirectories> + {% endfor %} +

+{% if folder %} +

You can upload your photographs here. +

You cannot create sub-folders here. +

Note that only photo image files are accepted: all other types of files are refused. +{% else %} +

You can upload your photographs to any of these folders, and you can create a new folder in your name for your photos. +

Note that only photo image files are accepted: all other types of files are refused. +


+

Create new Photographer folder in /photos/{{year}}/

+ + + +
+
+ {% csrf_token %} +
+ + + +


+ +
+
+

+ +{% endif %} +


+ + +{% endblock %} \ No newline at end of file diff --git a/urls.py b/urls.py index 466cb78..47f2050 100644 --- a/urls.py +++ b/urls.py @@ -10,7 +10,7 @@ from django.urls import path, reverse, resolve from troggle.core.views import caves, statistics, survex from troggle.core.views.scans import scansingle, singlewallet, allwallets from troggle.core.views.drawings import dwgallfiles, dwgfilesingle -from troggle.core.views.uploads import dwgupload, scanupload +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 @@ -86,9 +86,11 @@ trogglepatterns = [ re_path(r'^admin/', admin.site.urls), # includes admin login & logout urls # Uploads - uploading a file - path('scanupload/', scanupload, name='scanupload'), # wallet=2020#01, not a path - path('dwgupload/', dwgupload, name='dwgupload'), - path('dwgupload/', dwgupload, name='dwgupload'), + path('scanupload/', scanupload, name='scanupload'), # wallet=2020#01, not a path + path('photoupload/', photoupload, name='photoupload'), # restricted to current year + path('photoupload/', photoupload, name='photoupload'), # restricted to current year + path('dwgupload/', dwgupload, name='dwgupload'), + path('dwgupload/', dwgupload, name='dwgupload'), path('dwguploadnogit/', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing path('dwguploadnogit/', dwgupload, {'gitdisable': 'yes'}, name='dwguploadnogit'), # used in testing