refactor views

This commit is contained in:
James Ravenscroft 2024-12-08 15:51:02 +00:00
parent 5cd4de935f
commit 45e7da8ecf
9 changed files with 222 additions and 57 deletions

4
.gitignore vendored
View File

@ -160,3 +160,7 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
thumbnails/
uploads/

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2.16 on 2024-12-08 15:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('webui', '0002_imagememo'),
]
operations = [
migrations.AddField(
model_name='imagememo',
name='image_mimetype',
field=models.CharField(default='image/jpeg', max_length=256),
preserve_default=False,
),
migrations.AlterField(
model_name='imagememo',
name='image',
field=models.ImageField(upload_to='uploads/%Y/%m/%d'),
),
]

View File

@ -42,6 +42,9 @@ class UserManager(BaseUserManager):
class ImageMemo(models.Model): class ImageMemo(models.Model):
"""Model definition for ImageMemo.""" """Model definition for ImageMemo."""
id = models.UUIDField(primary_key=True, default=uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
image_mimetype = models.CharField(max_length=256)
image = models.ImageField(upload_to='uploads/%Y/%m/%d') image = models.ImageField(upload_to='uploads/%Y/%m/%d')
content = models.TextField() content = models.TextField()

View File

@ -13,9 +13,8 @@
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{% for document in documents %} {% for document in documents %}
<div <div class="bg-white p-6 rounded-lg shadow border-2 border-dotted border-gray-300">
class="bg-white p-6 rounded-lg shadow border-2 border-dotted border-gray-300" <img src="{% url 'document_thumbnail' pk=document.id %}" alt="{{ document.title }} thumbnail" class="w-full h-48 object-cover mb-4 rounded">
>
<h3 class="text-xl font-semibold mb-2">{{ document.title }}</h3> <h3 class="text-xl font-semibold mb-2">{{ document.title }}</h3>
<p class="text-gray-600 mb-4"> <p class="text-gray-600 mb-4">
Analyzed on: {{ document.analysis_date }} Analyzed on: {{ document.analysis_date }}
@ -40,13 +39,19 @@
{% endfor %} {% endfor %}
</div> </div>
</section> </section>
<section class="text-center"> <section class="text-center">
<h2 class="text-3xl font-bold text-gray-800 mb-6">Upload a New Document</h2> <h2 class="text-3xl font-bold text-gray-800 mb-6">Upload a New Document</h2>
<a <form action="{% url 'upload_document' %}" method="post" enctype="multipart/form-data">
href="{% url 'upload_document' %}" {% csrf_token %}
class="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition duration-300" <div class="mb-4">
>Upload Document</a <input type="file" name="document" id="document" class="hidden" accept=".png,.jpg,.jpeg">
> <label for="document" class="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition duration-300 cursor-pointer inline-block">
Choose File
</label>
</div>
<button type="submit" class="bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600 transition duration-300">
Upload Document
</button>
</form>
</section> </section>
{% endblock %} {% endblock %}

View File

@ -5,7 +5,14 @@ from . import views
urlpatterns = [ urlpatterns = [
path("", views.index, name="index"), path("", views.index, name="index"),
path("dashboard", views.dashboard, name="dashboard"), path("dashboard", views.dashboard, name="dashboard"),
path("settings", views.settings, name='settings'), path("settings", views.settings, name="settings"),
path("documents/upload", views.upload_document, name="upload_document"), path("documents/upload", views.upload_document, name="upload_document"),
path("documents/<str:pk>", views.view_document, name="view_document"),
path(
"documents/<str:pk>/thumbnail", views.document_thumbnail, name="document_thumbnail"
),
path(
"documents/<str:pk>/download", views.download_document, name="download_document"
),
path("auth/register", views.register, name="register"), path("auth/register", views.register, name="register"),
] ]

View File

@ -1,47 +0,0 @@
import logging
from django.contrib import messages
from django.shortcuts import redirect, render
from django.http import HttpRequest, HttpResponse
from django import conf, forms
from .models import User
from .forms import RegisterForm
logger = logging.getLogger(__name__)
def index(request):
# return HttpResponse("Hello, world. You're at the polls index.")
return render(request, 'index.html')
def dashboard(request):
return render(request, 'dashboard.html')
def settings(request):
return render(request, 'settings.html')
def upload_document(request):
return render(request, 'upload.html')
def register(request: HttpRequest):
# if the form is not submitted yet, return the form
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Registration successful!')
return redirect('login')
else:
form = RegisterForm()
return render(request, 'register.html', {'form': form})

View File

@ -0,0 +1,82 @@
import logging
import os
from django.contrib import messages
from django.shortcuts import redirect, render
from django.http import HttpRequest
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from ..models import ImageMemo
from django.contrib.auth.decorators import login_required
logger = logging.getLogger(__name__)
from .thumbnail import document_thumbnail
from .register import register
def index(request):
# return HttpResponse("Hello, world. You're at the polls index.")
return render(request, "index.html")
__all__ = ["index", "document_thumbnail", "register", "dashboard", "settings", "view_document", "download_document", "upload_document"]
@login_required
def dashboard(request: HttpRequest):
documents = ImageMemo.objects.filter(author__id=request.user.id).order_by(
"-updated_at"
)
context = {"documents": documents}
return render(request, "dashboard.html", context)
@login_required
def settings(request):
return render(request, "settings.html")
@login_required
def view_document(request):
return render(request, "document.html")
@login_required
def download_document(request):
return render(request, "document.html")
@login_required
def upload_document(request):
if request.method == "POST" and request.FILES.get("document"):
uploaded_file = request.FILES["document"]
# Check if the file is an image
if not uploaded_file.content_type.startswith("image/"):
messages.error(request, "Please upload an image file.")
return redirect("dashboard")
# Save the image
file_name = default_storage.save(
f"uploads/{uploaded_file.name}", ContentFile(uploaded_file.read())
)
# Create an ImageMemo instance
image_memo = ImageMemo(
image=file_name,
content="", # You can add initial content here if needed
author=request.user, # Assuming the user is authenticated
)
image_memo.save()
messages.success(request, "Image uploaded successfully!")
return redirect("dashboard") # Redirect to dashboard or appropriate page

View File

@ -0,0 +1,27 @@
import logging
import os
from django.contrib import messages
from django.shortcuts import redirect, render
from django.http import HttpRequest
from ..forms import RegisterForm
logger = logging.getLogger(__name__)
def register(request: HttpRequest):
# if the form is not submitted yet, return the form
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Registration successful!")
return redirect("login")
else:
form = RegisterForm()
return render(request, "register.html", {"form": form})

View File

@ -0,0 +1,60 @@
import os
from PIL import Image
from io import BytesIO
from django.core.files.storage import default_storage
from django import conf
from django.http import HttpRequest, HttpResponse
from django.contrib.auth.decorators import login_required
from ..models import ImageMemo
@login_required
def document_thumbnail(request: HttpRequest, pk: str):
"""Given a document uuid, look it up, ensure that it belongs to the current user and respond with a thumbnail"""
# find document with given ID (pk path param) and current user id
document = ImageMemo.objects.filter(id=pk, author__id=request.user.id).first()
if not document:
return HttpResponse("Document not found", status_code=404)
# look up the file on disk
# get thumb directory from django setting
thumbnail_dir = getattr(conf.settings, "THUMBNAIL_DIR", "thumbnails")
thumb_max_width = getattr(conf.settings, "THUMBNAIL_MAX_WIDTH", 420)
thumb_path = os.path.join(thumbnail_dir, str(document.id) + ".jpg")
if not os.path.exists(thumb_path):
if not os.path.exists(thumbnail_dir):
os.makedirs(thumbnail_dir)
# Open the image using PIL
image = Image.open(default_storage.open(document.image.name))
# get the image width and height
width = int(image.size[0])
height = int(image.size[1])
# find the ratio of the width to height
ratio = round(width / float(height), 3)
# max width of thumbnail is 240, calculate height based on ratio
thumb_height = int(thumb_max_width * ratio)
# Create a thumbnail
image.thumbnail((thumb_max_width, thumb_height)) # Adjust size as needed
# Save the thumbnail to a BytesIO object
thumb_io = BytesIO()
image.save(thumb_path, format="JPEG")
thumb_io.seek(0)
# Return the thumbnail as an HTTP response
with open(thumb_path, "rb") as f:
return HttpResponse(f.read(), content_type="image/jpeg")