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): class PostDetails(DetailView):
model = Post model = Post
template_name = "post_details.html"

View File

@ -1,11 +1,33 @@
from django import forms from django import forms
from pyparsing import removeQuotes
from .models import UploadImage from .models import UploadImage
from django.forms import ClearableFileInput, HiddenInput
from django.contrib.auth.models import User
class DetectForm(forms.ModelForm): class MultipleFileInput(forms.ClearableFileInput):
class Meta: allow_multiple_selected = True
model = UploadImage
fields = [
"image", class MultipleFileField(forms.FileField):
] def __init__(self, *args, **kwargs):
labels = {"image": ""} 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) @method_decorator(login_required)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request.FILES) form = self.form_class(request.POST, request.FILES)
files = request.FILES.getlist("image")
predictions = []
if form.is_valid(): if form.is_valid():
image = form.save(commit=False) for f in files:
image.owner = request.user image = UploadImage(
image.save() image=f,
prediciton_results = predict_image(image) )
image.predicted_image_url = ( image.owner = request.user
f"{image.image.name}_predicted/{image.image.name.split('/')[-1]}" image.save()
) prediciton_results = predict_image(image)
image.save() image.predicted_image_url = (
PredictedImage.objects.create( f"{image.image.name}_predicted/{image.image.name.split('/')[-1]}"
original_image=image, )
image=image.predicted_image_url, image.save()
confidence=prediciton_results[0]["confidence"], try:
class_name=prediciton_results[0]["name"], 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( return render(
request, request,
"upload.html", "results.html",
{ {
"img_saved": True, "img_saved": True,
"img_url": image.predicted_image_url, "img_url": predictions,
}, },
) )
else: else:
@ -53,7 +69,7 @@ class ListHistory(LoginRequiredMixin, ListView):
model = PredictedImage model = PredictedImage
queryset = PredictedImage.objects.all() queryset = PredictedImage.objects.all()
template_name = "history.html" template_name = "history.html"
paginate_by = 4 paginate_by = 3
def get_queryset(self) -> QuerySet[Any]: def get_queryset(self) -> QuerySet[Any]:
queryset = PredictedImage.objects.filter( 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{ .top-menu{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 5%;
justify-content:flex-end; justify-content:flex-end;
align-items: center; align-items: center;
background-color:lightgray; background-color:lightgray;
margin-bottom:5px; margin-bottom:5px;
height: 45px;
border: grey solid; border: grey solid;
border-width: 0px 2px 2px 2px; 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 { .upload_field {
margin: auto; margin: auto;
display: flex; display: flex;
flex-direction: column;
justify-content: right; justify-content: right;
flex-basis: auto; flex-basis: auto;
} }
@ -48,6 +49,7 @@ form{
.upload_button{ .upload_button{
display:flex; display:flex;
flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
align-items: 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"> <div class="footer">
<p>Footer</p> <p>Footer</p>
</div> </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> </body>
</html> </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 %} {% if not user.is_authenticated %}
<p id="description">Please login to submit image</p> <p id="description">Please login to submit image</p>
<button onclick="location.href='{% url 'login' %}'" id='submit' method="GET" type='button'>Login</button> <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> <p id="description">Choose image for analysis</p>
<input type="submit" id="submit" value="Submit"> <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%} {%endif%}
</div> </div>
<div class="upload_field"> <div class="upload_field">
<label for="id_image", class="upload_button"> <label for="id_image", class="upload_button" id="image-preview-container">
{{form.as_p}} {{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;"/>
<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%}
</label> </label>
</div> </div>
</form> </form>
<script> <script>
document.getElementById('id_image').addEventListener('change', function() { document.getElementById('id_image').addEventListener('change', function () {
var input = this; 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(); 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) { reader.onload = function(e) {
document.getElementById('image-preview').src = e.target.result; document.getElementById('image-preview').src = e.target.result;
document.getElementById('image-preview').style.display = 'block'; document.getElementById('image-preview').style.display = 'block';
} }
reader.readAsDataURL(input.files[0]);
reader.readAsDataURL(input.files[0]); }
} });
});
</script> </script>
</form> </form>
{%endblock content%} {%endblock content%}