Allow multiple file upload

This commit is contained in:
Piotr Szkudlarek 2023-12-19 17:33:46 +01:00
parent e146f16f56
commit a75c94d5c6
12 changed files with 234 additions and 44 deletions

View File

@ -12,3 +12,4 @@ class ListPosts(ListView):
class PostDetails(DetailView):
model = Post
template_name = "post_details.html"

View File

@ -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
)

View File

@ -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(

Binary file not shown.

View File

@ -0,0 +1,3 @@
.class{
display:flex;
}

View File

@ -16,13 +16,14 @@ body, html{
.top-menu{
display: flex;
flex-direction: row;
height: 5%;
justify-content:flex-end;
align-items: center;
background-color:lightgray;
margin-bottom:5px;
height: 45px;
border: grey solid;
border-width: 0px 2px 2px 2px;
transition: top 0.3s;
}

View File

@ -0,0 +1,64 @@
form{
height:100%;
width:100%;
display:flex;
flex-direction:row;
margin:auto;
}
.side_menu{
display: flex;
justify-content: center;
align-items:center;
flex-direction: column;
width: 25%;
background-color: lightgray;
border: grey solid;
border-width: 2px;
margin-bottom: 59px;
}
#description{
font-size: 40px;
text-align: center;
}
#submit{
margin-bottom: 40px;
background-color: chartreuse;
margin-top: auto;
height: 50px;
width: 80%;
border-radius: 25px;
border: 2px white;
box-shadow: 0 0 0 4px white;
font-size: 25px;
}
.upload_field {
margin: auto;
display: flex;
flex-direction: row;
justify-content: right;
width:645px;
height: 465px;
}
.upload_field label{
display:flex;
flex-direction: row;
overflow-x: scroll;
overflow-y: hidden;
}
.upload_field label img{
margin-right:5px;
display: block;
}

View File

@ -41,6 +41,7 @@ form{
.upload_field {
margin: auto;
display: flex;
flex-direction: column;
justify-content: right;
flex-basis: auto;
}
@ -48,6 +49,7 @@ form{
.upload_button{
display:flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-start;
}
@ -57,6 +59,8 @@ form{
}
.upload_field label img{
margin-bottom: 5px;
}

View File

@ -27,5 +27,17 @@
<div class="footer">
<p>Footer</p>
</div>
<script>
var prevScrollpos = window.pageYOffset;
window.onscroll = function() {
var currentScrollPos = window.pageYOffset;
if (prevScrollpos > currentScrollPos) {
document.getElementsByClassName("top-menu").style.top = "0";
} else {
document.getElementsByClassName("top-menu").style.top = "-50px";
}
prevScrollpos = currentScrollPos;
}
</script>
</body>
</html>

View File

@ -0,0 +1,19 @@
{%extends 'base.html'%}
{%load static%}
{%block extracss%}
<link rel="stylesheet" href="{% static 'DetectionApp/css/detection-detail.css' %}">
{%endblock extracss%}
{%block content%}
<div class="post">
<p class="title">{{object.title}}</p>
<p class="content">{{object.content}}</p>
<p class="author">{{object.author}}</p>
</div>
<div class="comments">
{%for comments in object.comment_set.all%}
<p>{{comments.author}}</p>
<p>{{comments.content}}</p>
<p>{{comments.post}}</p>
{%endfor%}
</div>
{%endblock content%}

View File

@ -0,0 +1,26 @@
{% extends 'base.html' %}
{%load static%}
{%block extracss%}
<link rel="stylesheet" href="{%static 'DetectionApp/css/results.css' %}">
{%endblock extracss%}
{%block content%}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="side_menu">
{% if not user.is_authenticated %}
<p id="description">Please login to see results</p>
<button onclick="location.href='{% url 'login' %}'" id='submit' method="GET" type='button'>Login</button>
{% else %}
<p id="description">Results:</p>
<button onclick="location.href='{% url 'detect' %}'" id='submit' method="GET" type='button'>Submit again</button>
{%endif%}
</div>
<div class="upload_field">
<label>
{%for img in img_url%}
<img src="{%get_media_prefix%}{{img.predicted_image_url}}" alt="upload_image" style="width:640px; height:460px;">
{%endfor%}
</label>
</div>
</form>
{%endblock content%}

View File

@ -10,40 +10,62 @@
{% if not user.is_authenticated %}
<p id="description">Please login to submit image</p>
<button onclick="location.href='{% url 'login' %}'" id='submit' method="GET" type='button'>Login</button>
{% elif img_saved is None %}
{% else %}
<p id="description">Choose image for analysis</p>
<input type="submit" id="submit" value="Submit">
{% else %}
<p id="description">Photo saved</p>
<button onclick="location.href='{% url 'detect' %}'" id='submit' method="GET" type='button'>Submit again</button>
{%endif%}
</div>
<div class="upload_field">
<label for="id_image", class="upload_button">
<div class="upload_field">
<label for="id_image", class="upload_button" id="image-preview-container">
{{form.as_p}}
{% if not img_url %}
<img id="image-preview" src="{% static 'DetectionApp/images/upload_img.png' %}" alt="Image Preview" style="width:640px; height:460px;"/>
{%else%}
<img src="{%get_media_prefix%}{{img_url}}" alt="upload_image" style="width:640px; height:460px;">
{%endif%}
<img id="image-preview" src="{% static 'DetectionApp/images/upload_img.png' %}" alt="Image Preview" style="width:640px; height:460px;"/>
</label>
</div>
</div>
</form>
<script>
document.getElementById('id_image').addEventListener('change', function() {
var input = this;
document.getElementById('id_image').addEventListener('change', function () {
var input = this;
var previewContainer = document.getElementById('image-preview-container');
if (input.files && input.files[0]) {
if (input.files && input.files.length > 1) {
document.getElementById('image-preview').style.display='none'
for (var i = 0; i < input.files.length; i++) {
(function (index) {
var reader = new FileReader();
reader.onload = function (e) {
// Create a new image element for each preview
var img = document.createElement('img');
img.src = e.target.result;
img.id = 'image-preview'
img.style.display = 'block';
img.style.width='640px'
img.style.height='460px'
img.style.marginRight="5px"
// Append the image element to the container
previewContainer.style.overflowY='hidden'
previewContainer.style.overflowX='scroll'
previewContainer.style.width='640px'
previewContainer.style.height='460px'
previewContainer.appendChild(img);
};
reader.readAsDataURL(input.files[index]);
})(i);
}
}else{
var reader = new FileReader();
reader.onload = function(e) {
document.getElementById('image-preview').src = e.target.result;
document.getElementById('image-preview').style.display = 'block';
}
reader.readAsDataURL(input.files[0]);
reader.readAsDataURL(input.files[0]);
}
});
}
});
</script>
</form>
{%endblock content%}