From a75c94d5c677f702cb41132e63d9aa1a00424a92 Mon Sep 17 00:00:00 2001 From: Piotr Szkudlarek Date: Tue, 19 Dec 2023 17:33:46 +0100 Subject: [PATCH] Allow multiple file upload --- PlanktonDetector/Community/views.py | 1 + PlanktonDetector/DetectionApp/forms.py | 36 ++++++++-- PlanktonDetector/DetectionApp/views.py | 50 +++++++++----- PlanktonDetector/db.sqlite3 | Bin 192512 -> 241664 bytes .../static/Community/css/post_details.css | 3 + .../static/DetectionApp/css/base.css | 3 +- .../static/DetectionApp/css/results.css | 64 ++++++++++++++++++ .../static/DetectionApp/css/upload.css | 6 +- PlanktonDetector/templates/base.html | 12 ++++ PlanktonDetector/templates/post_details.html | 19 ++++++ PlanktonDetector/templates/results.html | 26 +++++++ PlanktonDetector/templates/upload.html | 58 +++++++++++----- 12 files changed, 234 insertions(+), 44 deletions(-) create mode 100644 PlanktonDetector/static/Community/css/post_details.css create mode 100644 PlanktonDetector/static/DetectionApp/css/results.css create mode 100644 PlanktonDetector/templates/post_details.html create mode 100644 PlanktonDetector/templates/results.html diff --git a/PlanktonDetector/Community/views.py b/PlanktonDetector/Community/views.py index 50fb78a..99ce625 100644 --- a/PlanktonDetector/Community/views.py +++ b/PlanktonDetector/Community/views.py @@ -12,3 +12,4 @@ class ListPosts(ListView): class PostDetails(DetailView): model = Post + template_name = "post_details.html" diff --git a/PlanktonDetector/DetectionApp/forms.py b/PlanktonDetector/DetectionApp/forms.py index c2c108b..d53a209 100644 --- a/PlanktonDetector/DetectionApp/forms.py +++ b/PlanktonDetector/DetectionApp/forms.py @@ -1,11 +1,33 @@ from django import forms +from pyparsing import removeQuotes from .models import UploadImage +from django.forms import ClearableFileInput, HiddenInput +from django.contrib.auth.models import User -class DetectForm(forms.ModelForm): - class Meta: - model = UploadImage - fields = [ - "image", - ] - labels = {"image": ""} +class MultipleFileInput(forms.ClearableFileInput): + allow_multiple_selected = True + + +class MultipleFileField(forms.FileField): + def __init__(self, *args, **kwargs): + kwargs.setdefault("widget", MultipleFileInput()) + super().__init__(*args, **kwargs) + + def clean(self, data, initial=None): + single_file_clean = super().clean + if isinstance(data, (list, tuple)): + result = [single_file_clean(d, initial) for d in data] + else: + result = single_file_clean(data, initial) + return result + + +class DetectForm(forms.Form): + image = MultipleFileField() + predicted_image_url = forms.CharField( + max_length=500, widget=HiddenInput(), required=False + ) + owner = forms.ModelChoiceField( + queryset=User.objects.all(), widget=HiddenInput(), required=False + ) diff --git a/PlanktonDetector/DetectionApp/views.py b/PlanktonDetector/DetectionApp/views.py index c8cd5ce..ef076f7 100644 --- a/PlanktonDetector/DetectionApp/views.py +++ b/PlanktonDetector/DetectionApp/views.py @@ -22,27 +22,43 @@ class DetectView(View): @method_decorator(login_required) def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request.FILES) + files = request.FILES.getlist("image") + predictions = [] if form.is_valid(): - image = form.save(commit=False) - image.owner = request.user - image.save() - prediciton_results = predict_image(image) - image.predicted_image_url = ( - f"{image.image.name}_predicted/{image.image.name.split('/')[-1]}" - ) - image.save() - PredictedImage.objects.create( - original_image=image, - image=image.predicted_image_url, - confidence=prediciton_results[0]["confidence"], - class_name=prediciton_results[0]["name"], - ) + for f in files: + image = UploadImage( + image=f, + ) + image.owner = request.user + image.save() + prediciton_results = predict_image(image) + image.predicted_image_url = ( + f"{image.image.name}_predicted/{image.image.name.split('/')[-1]}" + ) + image.save() + try: + results_metrics = prediciton_results[0] + except IndexError as e: + PredictedImage.objects.create( + original_image=image, + image=image.predicted_image_url, + confidence=0.0, + class_name="no predictions", + ) + else: + PredictedImage.objects.create( + original_image=image, + image=image.predicted_image_url, + confidence=results_metrics["confidence"], + class_name=results_metrics["name"], + ) + predictions.append(image) return render( request, - "upload.html", + "results.html", { "img_saved": True, - "img_url": image.predicted_image_url, + "img_url": predictions, }, ) else: @@ -53,7 +69,7 @@ class ListHistory(LoginRequiredMixin, ListView): model = PredictedImage queryset = PredictedImage.objects.all() template_name = "history.html" - paginate_by = 4 + paginate_by = 3 def get_queryset(self) -> QuerySet[Any]: queryset = PredictedImage.objects.filter( diff --git a/PlanktonDetector/db.sqlite3 b/PlanktonDetector/db.sqlite3 index 8352d6e6a878afa119e94aca5e05de48b592a742..47ebd67fafc926dd0409058a13eb8bae472920aa 100644 GIT binary patch literal 241664 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 delta 700 zcmZp8z}N7Adx8`n<1PjU27Msb1!Crj8fHw4yEY~)k(c1)JI}!Xl3$;HH-8y_H~$)b zSH2H?=lND{Ry644o4is_m5o7Ol-Zea`oiT*(u}N=Kj_J_F-+i(U{ILoD6?5#f3X9< zfuWUwrInGPo~faQp{eEOhxwH{3KbP)6-JpRWhv=K+36;E85Q}tWjV$s>B)vg*_jn4 z#gnV%Z1s1^j<7OGD|9VMDRW8jGAf7+Hp$N_i*)jI_A_(|4K&WFEcW%u4hk`>EU<_- zj5IPZGS)RT(ls(yK-g(yZfI;!!ouQP={UJ?y~5^sa|@Z6xAS{!7A!F1S5aa1WhCU3 z=A8B0bJjC*1|azaZ0huu|BMaHvixyV*_o{Cc@GUJ)FsLK&58=wc$k>%HU|pKV4S{z zn~7z55# z&%pni{|o

Footer

+ \ No newline at end of file diff --git a/PlanktonDetector/templates/post_details.html b/PlanktonDetector/templates/post_details.html new file mode 100644 index 0000000..c0fb22b --- /dev/null +++ b/PlanktonDetector/templates/post_details.html @@ -0,0 +1,19 @@ +{%extends 'base.html'%} +{%load static%} +{%block extracss%} + +{%endblock extracss%} +{%block content%} +
+

{{object.title}}

+

{{object.content}}

+

{{object.author}}

+
+
+ {%for comments in object.comment_set.all%} +

{{comments.author}}

+

{{comments.content}}

+

{{comments.post}}

+ {%endfor%} +
+{%endblock content%} \ No newline at end of file diff --git a/PlanktonDetector/templates/results.html b/PlanktonDetector/templates/results.html new file mode 100644 index 0000000..6b39262 --- /dev/null +++ b/PlanktonDetector/templates/results.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} +{%load static%} +{%block extracss%} + +{%endblock extracss%} +{%block content%} +
+ {% csrf_token %} +
+ {% if not user.is_authenticated %} +

Please login to see results

+ + {% else %} +

Results:

+ + {%endif%} +
+
+ +
+
+ {%endblock content%} \ No newline at end of file diff --git a/PlanktonDetector/templates/upload.html b/PlanktonDetector/templates/upload.html index 2a564a1..74f0d3b 100644 --- a/PlanktonDetector/templates/upload.html +++ b/PlanktonDetector/templates/upload.html @@ -10,40 +10,62 @@ {% if not user.is_authenticated %}

Please login to submit image

- {% elif img_saved is None %} + {% else %}

Choose image for analysis

- {% else %} -

Photo saved

- {%endif%} -
-
{%endblock content%} \ No newline at end of file