diff --git a/PlanktonDetector/Community/__init__.py b/PlanktonDetector/Community/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PlanktonDetector/Community/admin.py b/PlanktonDetector/Community/admin.py new file mode 100644 index 0000000..2d5acdf --- /dev/null +++ b/PlanktonDetector/Community/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from . import models + +# Register your models here. +admin.site.register(models.Comment) +admin.site.register(models.Post) diff --git a/PlanktonDetector/Community/apps.py b/PlanktonDetector/Community/apps.py new file mode 100644 index 0000000..52470e6 --- /dev/null +++ b/PlanktonDetector/Community/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CommunityConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "Community" diff --git a/PlanktonDetector/Community/migrations/0001_initial.py b/PlanktonDetector/Community/migrations/0001_initial.py new file mode 100644 index 0000000..13bdbfe --- /dev/null +++ b/PlanktonDetector/Community/migrations/0001_initial.py @@ -0,0 +1,67 @@ +# Generated by Django 4.2.7 on 2023-12-11 15:42 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="Post", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=500)), + ("content", models.TextField()), + ( + "author", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + ), + migrations.CreateModel( + name="Comment", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("content", models.TextField()), + ( + "author", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "post", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="Community.post" + ), + ), + ], + ), + ] diff --git a/PlanktonDetector/Community/migrations/0002_post_date_pub.py b/PlanktonDetector/Community/migrations/0002_post_date_pub.py new file mode 100644 index 0000000..7abfcf9 --- /dev/null +++ b/PlanktonDetector/Community/migrations/0002_post_date_pub.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2023-12-11 16:58 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + dependencies = [ + ("Community", "0001_initial"), + ] + + operations = [ + migrations.AddField( + model_name="post", + name="date_pub", + field=models.DateField( + auto_now_add=True, default=django.utils.timezone.now + ), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/Community/migrations/__init__.py b/PlanktonDetector/Community/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PlanktonDetector/Community/models.py b/PlanktonDetector/Community/models.py new file mode 100644 index 0000000..aed7013 --- /dev/null +++ b/PlanktonDetector/Community/models.py @@ -0,0 +1,17 @@ +from django.db import models +from django.contrib.auth.models import User + +# Create your models here. + + +class Post(models.Model): + title = models.CharField(max_length=500) + content = models.TextField() + author = models.ForeignKey(User, on_delete=models.CASCADE, null=False) + date_pub = models.DateField(auto_now_add=True) + + +class Comment(models.Model): + author = models.ForeignKey(User, on_delete=models.CASCADE, null=False) + content = models.TextField() + post = models.ForeignKey(Post, on_delete=models.CASCADE) diff --git a/PlanktonDetector/Community/tests.py b/PlanktonDetector/Community/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/PlanktonDetector/Community/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/PlanktonDetector/Community/urls.py b/PlanktonDetector/Community/urls.py new file mode 100644 index 0000000..c31225f --- /dev/null +++ b/PlanktonDetector/Community/urls.py @@ -0,0 +1,9 @@ +from django.urls import path +from django.conf import settings +from django.conf.urls.static import static +from . import views + +urlpatterns = [ + path("posts/", views.ListPosts.as_view(), name="posts"), + path("posts/", views.PostDetails.as_view(), name="post-details"), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/PlanktonDetector/Community/views.py b/PlanktonDetector/Community/views.py new file mode 100644 index 0000000..50fb78a --- /dev/null +++ b/PlanktonDetector/Community/views.py @@ -0,0 +1,14 @@ +from django.shortcuts import render +from django.views.generic import ListView, DetailView +from .models import Post, Comment + +# Create your views here. + + +class ListPosts(ListView): + model = Post + template_name = "list_posts.html" + + +class PostDetails(DetailView): + model = Post diff --git a/PlanktonDetector/DetectionApp/admin.py b/PlanktonDetector/DetectionApp/admin.py index 8c38f3f..b5e0d05 100644 --- a/PlanktonDetector/DetectionApp/admin.py +++ b/PlanktonDetector/DetectionApp/admin.py @@ -1,3 +1,5 @@ from django.contrib import admin +from . import models # Register your models here. +admin.site.register(models.UploadImage) diff --git a/PlanktonDetector/DetectionApp/forms.py b/PlanktonDetector/DetectionApp/forms.py index 0729d02..c2c108b 100644 --- a/PlanktonDetector/DetectionApp/forms.py +++ b/PlanktonDetector/DetectionApp/forms.py @@ -1,9 +1,11 @@ from django import forms -from .models import DetectImage +from .models import UploadImage + class DetectForm(forms.ModelForm): - class Meta: - model = DetectImage - fields = "__all__" - labels={"image":""} \ No newline at end of file + model = UploadImage + fields = [ + "image", + ] + labels = {"image": ""} diff --git a/PlanktonDetector/DetectionApp/migrations/0003_detectimage_owner.py b/PlanktonDetector/DetectionApp/migrations/0003_detectimage_owner.py new file mode 100644 index 0000000..69b6a90 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0003_detectimage_owner.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.7 on 2023-12-12 16:31 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("DetectionApp", "0002_alter_detectimage_image"), + ] + + operations = [ + migrations.AddField( + model_name="detectimage", + name="owner", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0004_detectimage_predicted_image_url.py b/PlanktonDetector/DetectionApp/migrations/0004_detectimage_predicted_image_url.py new file mode 100644 index 0000000..4a2d9b2 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0004_detectimage_predicted_image_url.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2023-12-12 21:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("DetectionApp", "0003_detectimage_owner"), + ] + + operations = [ + migrations.AddField( + model_name="detectimage", + name="predicted_image_url", + field=models.CharField(default="url", max_length=500), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0005_detectimage_date_predicted.py b/PlanktonDetector/DetectionApp/migrations/0005_detectimage_date_predicted.py new file mode 100644 index 0000000..f085876 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0005_detectimage_date_predicted.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.7 on 2023-12-12 21:21 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + dependencies = [ + ("DetectionApp", "0004_detectimage_predicted_image_url"), + ] + + operations = [ + migrations.AddField( + model_name="detectimage", + name="date_predicted", + field=models.DateTimeField( + auto_now_add=True, default=django.utils.timezone.now + ), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0006_predictedimage.py b/PlanktonDetector/DetectionApp/migrations/0006_predictedimage.py new file mode 100644 index 0000000..b81225d --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0006_predictedimage.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.7 on 2023-12-12 22:46 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("DetectionApp", "0005_detectimage_date_predicted"), + ] + + operations = [ + migrations.CreateModel( + name="PredictedImage", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("image", models.ImageField(upload_to="plankton/%Y/%m/%d/None")), + ("confidence", models.FloatField()), + ("class_name", models.CharField(max_length=100)), + ( + "original_image", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + to="DetectionApp.detectimage", + ), + ), + ], + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0007_remove_detectimage_date_predicted_and_more.py b/PlanktonDetector/DetectionApp/migrations/0007_remove_detectimage_date_predicted_and_more.py new file mode 100644 index 0000000..5dd279d --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0007_remove_detectimage_date_predicted_and_more.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.7 on 2023-12-13 00:25 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + dependencies = [ + ("DetectionApp", "0006_predictedimage"), + ] + + operations = [ + migrations.RemoveField( + model_name="detectimage", + name="date_predicted", + ), + migrations.AddField( + model_name="predictedimage", + name="date_predicted", + field=models.DateTimeField( + auto_now_add=True, default=django.utils.timezone.now + ), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0008_predictedimage_owner.py b/PlanktonDetector/DetectionApp/migrations/0008_predictedimage_owner.py new file mode 100644 index 0000000..1b76f24 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0008_predictedimage_owner.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.7 on 2023-12-13 00:29 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("DetectionApp", "0007_remove_detectimage_date_predicted_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="predictedimage", + name="owner", + field=models.ForeignKey( + default=1, + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + preserve_default=False, + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0009_remove_predictedimage_owner.py b/PlanktonDetector/DetectionApp/migrations/0009_remove_predictedimage_owner.py new file mode 100644 index 0000000..6f199d4 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0009_remove_predictedimage_owner.py @@ -0,0 +1,16 @@ +# Generated by Django 4.2.7 on 2023-12-13 00:31 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("DetectionApp", "0008_predictedimage_owner"), + ] + + operations = [ + migrations.RemoveField( + model_name="predictedimage", + name="owner", + ), + ] diff --git a/PlanktonDetector/DetectionApp/migrations/0010_rename_detectimage_uploadimage.py b/PlanktonDetector/DetectionApp/migrations/0010_rename_detectimage_uploadimage.py new file mode 100644 index 0000000..22dca81 --- /dev/null +++ b/PlanktonDetector/DetectionApp/migrations/0010_rename_detectimage_uploadimage.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2023-12-13 01:08 + +from django.conf import settings +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("DetectionApp", "0009_remove_predictedimage_owner"), + ] + + operations = [ + migrations.RenameModel( + old_name="DetectImage", + new_name="UploadImage", + ), + ] diff --git a/PlanktonDetector/DetectionApp/models.py b/PlanktonDetector/DetectionApp/models.py index 371f9f5..4518c20 100644 --- a/PlanktonDetector/DetectionApp/models.py +++ b/PlanktonDetector/DetectionApp/models.py @@ -1,11 +1,30 @@ from django.db import models from django.core.validators import FileExtensionValidator +from django.contrib.auth.models import User # Create your models here. -class DetectImage(models.Model): +class UploadImage(models.Model): image = models.ImageField( upload_to="plankton/%Y/%m/%d/", validators=[FileExtensionValidator(allowed_extensions=["jpg", "png"])], ) + predicted_image_url = models.CharField(max_length=500) + owner = models.ForeignKey(User, on_delete=models.CASCADE) + + +class PredictedImage(models.Model): + original_image = models.OneToOneField(UploadImage, on_delete=models.CASCADE) + image = models.ImageField(upload_to=f"plankton/%Y/%m/%d/{original_image.name}") + confidence = models.FloatField() + class_name = models.CharField(max_length=100) + date_predicted = models.DateTimeField(auto_now_add=True) + + @property + def get_owner(self): + return self.original_image.owner + + @property + def get_original_image(self): + return self.original_image.image diff --git a/PlanktonDetector/DetectionApp/urls.py b/PlanktonDetector/DetectionApp/urls.py index 160f192..7cc7390 100644 --- a/PlanktonDetector/DetectionApp/urls.py +++ b/PlanktonDetector/DetectionApp/urls.py @@ -6,7 +6,8 @@ from django.contrib.auth import urls urlpatterns = [ path("detect/", views.DetectView.as_view(), name="detect"), - path("login/", views.LoginView.as_view(), name="login"), - path("logout/", views.logout_view, name="logout"), - path("register/", views.SignupView.as_view(), name="signup"), + path("history/", views.ListHistory.as_view(), name="history"), + path( + "detection/", views.DetectionDetails.as_view(), name="detection-details" + ), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/PlanktonDetector/DetectionApp/utils.py b/PlanktonDetector/DetectionApp/utils.py new file mode 100644 index 0000000..be0decc --- /dev/null +++ b/PlanktonDetector/DetectionApp/utils.py @@ -0,0 +1,20 @@ +import json +from django.core.files import File +from PIL import Image +from io import BytesIO +from django.conf import settings +from ultralytics import YOLO + +MODEL = YOLO("best.pt") + + +def predict_image(image): + results = MODEL.predict( + image.image.path, + save=True, + project=settings.MEDIA_ROOT, + name=f"{image.image.name}_predicted", + imgsz=[640, 640], + ) + x = json.loads(results[0].tojson()) + return x diff --git a/PlanktonDetector/DetectionApp/views.py b/PlanktonDetector/DetectionApp/views.py index eb2bcf5..c8cd5ce 100644 --- a/PlanktonDetector/DetectionApp/views.py +++ b/PlanktonDetector/DetectionApp/views.py @@ -1,13 +1,14 @@ +from typing import Any +from django.db.models.query import QuerySet from django.shortcuts import render, redirect from django.views import View from .forms import DetectForm -from django.conf import settings -from ultralytics import YOLO -from django.contrib.auth.forms import AuthenticationForm, UserCreationForm -from django.contrib.auth import authenticate, login, logout - -# Create your views here. -MODEL = YOLO("best.pt") +from django.views.generic import ListView, DetailView +from django.contrib.auth.decorators import login_required +from django.utils.decorators import method_decorator +from .models import UploadImage, PredictedImage +from .utils import predict_image +from django.contrib.auth.mixins import LoginRequiredMixin class DetectView(View): @@ -18,68 +19,49 @@ class DetectView(View): form = self.form_class() return render(request, "upload.html", {"form": form}) + @method_decorator(login_required) def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request.FILES) if form.is_valid(): - image = form.save() - MODEL.predict( - image.image.path, - save=True, - project=settings.MEDIA_ROOT, - name=f"{image.image.name}_predicted", - imgsz=[640, 640], + 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"], ) - saved = form.is_valid() return render( request, "upload.html", { - "img_saved": saved, - "img_path": f"{image.image.name}_predicted/{image.image.name.split('/')[-1]}", + "img_saved": True, + "img_url": image.predicted_image_url, }, ) else: return render(request, "upload.html", {"form": form}) -class LoginView(View): - form_class = AuthenticationForm - template_name = "login_signup.html" +class ListHistory(LoginRequiredMixin, ListView): + model = PredictedImage + queryset = PredictedImage.objects.all() + template_name = "history.html" + paginate_by = 4 - def get(self, request, *args, **kwargs): - form = self.form_class() - return render(request, self.template_name, {"form": form}) - - def post(self, request, *args, **kwargs): - form = self.form_class(data=request.POST) - if form.is_valid(): - user = authenticate( - username=form.cleaned_data["username"], - password=form.cleaned_data["password"], - ) - if user is not None: - login(request, user) - return redirect("detect") - return render(request, self.template_name, {"form": form}) + def get_queryset(self) -> QuerySet[Any]: + queryset = PredictedImage.objects.filter( + original_image__owner=self.request.user + ).order_by("-date_predicted") + return queryset -class SignupView(View): - form_class = UserCreationForm - template_name = "login_signup.html" - - def get(self, request, *args, **kwargs): - form = self.form_class() - return render(request, self.template_name, {"form": form, "signup": True}) - - def post(self, request, *args, **kwargs): - form = self.form_class(data=request.POST) - if form.is_valid(): - user = form.save() - login(request, user) - return redirect("detect") - return render(request, self.template_name, {"form": form, "signup": True}) - - -def logout_view(request): - logout(request) - return redirect("detect") +class DetectionDetails(LoginRequiredMixin, DetailView): + model = PredictedImage + template_name = "detection_detail.html" diff --git a/PlanktonDetector/PlanktonDetector/settings.py b/PlanktonDetector/PlanktonDetector/settings.py index 66a1b06..37a3d56 100644 --- a/PlanktonDetector/PlanktonDetector/settings.py +++ b/PlanktonDetector/PlanktonDetector/settings.py @@ -39,6 +39,7 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.staticfiles", "DetectionApp", + "Community", ] MIDDLEWARE = [ diff --git a/PlanktonDetector/PlanktonDetector/urls.py b/PlanktonDetector/PlanktonDetector/urls.py index c1e0330..33e39cb 100644 --- a/PlanktonDetector/PlanktonDetector/urls.py +++ b/PlanktonDetector/PlanktonDetector/urls.py @@ -16,8 +16,12 @@ Including another URLconf """ from django.contrib import admin from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), - path("", include("DetectionApp.urls")) -] + path("", include("DetectionApp.urls")), + path("accounts/", include("UserManagement.urls")), + path("community/", include("Community.urls")), +] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/PlanktonDetector/UserManagement/__init__.py b/PlanktonDetector/UserManagement/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PlanktonDetector/UserManagement/admin.py b/PlanktonDetector/UserManagement/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/PlanktonDetector/UserManagement/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/PlanktonDetector/UserManagement/apps.py b/PlanktonDetector/UserManagement/apps.py new file mode 100644 index 0000000..d7c949f --- /dev/null +++ b/PlanktonDetector/UserManagement/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UsermanagementConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "UserManagement" diff --git a/PlanktonDetector/UserManagement/migrations/__init__.py b/PlanktonDetector/UserManagement/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/PlanktonDetector/UserManagement/models.py b/PlanktonDetector/UserManagement/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/PlanktonDetector/UserManagement/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/PlanktonDetector/UserManagement/tests.py b/PlanktonDetector/UserManagement/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/PlanktonDetector/UserManagement/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/PlanktonDetector/UserManagement/urls.py b/PlanktonDetector/UserManagement/urls.py new file mode 100644 index 0000000..b1a3ee4 --- /dev/null +++ b/PlanktonDetector/UserManagement/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path("login/", views.LoginView.as_view(), name="login"), + path("logout/", views.logout_view, name="logout"), + path("register/", views.SignupView.as_view(), name="signup"), +] diff --git a/PlanktonDetector/UserManagement/views.py b/PlanktonDetector/UserManagement/views.py new file mode 100644 index 0000000..94df782 --- /dev/null +++ b/PlanktonDetector/UserManagement/views.py @@ -0,0 +1,46 @@ +from django.shortcuts import render, redirect +from django.contrib.auth.forms import AuthenticationForm, UserCreationForm +from django.contrib.auth import authenticate, login, logout +from django.views import View + +class LoginView(View): + form_class = AuthenticationForm + template_name = "login_signup.html" + + def get(self, request, *args, **kwargs): + form = self.form_class() + return render(request, self.template_name, {"form": form}) + + def post(self, request, *args, **kwargs): + form = self.form_class(data=request.POST) + if form.is_valid(): + user = authenticate( + username=form.cleaned_data["username"], + password=form.cleaned_data["password"], + ) + if user is not None: + login(request, user) + return redirect("detect") + return render(request, self.template_name, {"form": form}) + + +class SignupView(View): + form_class = UserCreationForm + template_name = "login_signup.html" + + def get(self, request, *args, **kwargs): + form = self.form_class() + return render(request, self.template_name, {"form": form, "signup": True}) + + def post(self, request, *args, **kwargs): + form = self.form_class(data=request.POST) + if form.is_valid(): + user = form.save() + login(request, user) + return redirect("detect") + return render(request, self.template_name, {"form": form, "signup": True}) + + +def logout_view(request): + logout(request) + return redirect("detect") diff --git a/PlanktonDetector/db.sqlite3 b/PlanktonDetector/db.sqlite3 index 6eb5dc8..8352d6e 100644 Binary files a/PlanktonDetector/db.sqlite3 and b/PlanktonDetector/db.sqlite3 differ diff --git a/PlanktonDetector/static/Community/css/list_posts.css b/PlanktonDetector/static/Community/css/list_posts.css new file mode 100644 index 0000000..17adc82 --- /dev/null +++ b/PlanktonDetector/static/Community/css/list_posts.css @@ -0,0 +1,38 @@ +.post_list{ + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 100%; +} + +h2{ + margin-bottom:25px; +} + +ul{ + list-style-type: none; +} + +.post_list a{ + text-decoration: none; + width: 100%; + color: black; +} + +.post_details{ + display:flex; + width: 50%; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; + margin-bottom: 25px; +} + +.date_author{ + display: flex; + width: 100%; + flex-direction: row; + align-items: flex-start; + justify-content: space-between; +} \ No newline at end of file diff --git a/PlanktonDetector/static/DetectionApp/css/base.css b/PlanktonDetector/static/DetectionApp/css/base.css index e665d26..bf17a48 100644 --- a/PlanktonDetector/static/DetectionApp/css/base.css +++ b/PlanktonDetector/static/DetectionApp/css/base.css @@ -28,6 +28,10 @@ body, html{ .footer{ display:flex; + position:fixed; + bottom: 0; + right: 0; + left:0; flex-direction: row; justify-content: center; align-items: center; diff --git a/PlanktonDetector/static/DetectionApp/css/detection_detail.css b/PlanktonDetector/static/DetectionApp/css/detection_detail.css new file mode 100644 index 0000000..440f7ed --- /dev/null +++ b/PlanktonDetector/static/DetectionApp/css/detection_detail.css @@ -0,0 +1,7 @@ +.history_list{ + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 100%; +} diff --git a/PlanktonDetector/static/DetectionApp/css/history.css b/PlanktonDetector/static/DetectionApp/css/history.css new file mode 100644 index 0000000..3af0310 --- /dev/null +++ b/PlanktonDetector/static/DetectionApp/css/history.css @@ -0,0 +1,38 @@ +.history_list{ + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 100%; +} + +h2{ + margin-bottom:25px; +} + +ul{ + list-style-type: none; +} + +.history_list a{ + text-decoration: none; + width: 50%; + color: black; +} + +.history_details{ + display:flex; + width: 100%; + flex-direction: row; + align-items: flex-start; + justify-content: space-evenly; + margin-bottom: 25px; +} + +.date_author{ + display: flex; + width: 100%; + flex-direction: column; + align-items: flex-end; + justify-content: space-between; +} diff --git a/PlanktonDetector/static/DetectionApp/css/upload.css b/PlanktonDetector/static/DetectionApp/css/upload.css index efd0898..7b492bf 100644 --- a/PlanktonDetector/static/DetectionApp/css/upload.css +++ b/PlanktonDetector/static/DetectionApp/css/upload.css @@ -17,6 +17,7 @@ form{ background-color: lightgray; border: grey solid; border-width: 2px; + margin-bottom: 59px; } diff --git a/PlanktonDetector/templates/base.html b/PlanktonDetector/templates/base.html index 8ddf9b5..34a976b 100644 --- a/PlanktonDetector/templates/base.html +++ b/PlanktonDetector/templates/base.html @@ -14,9 +14,10 @@
- Placeholder + Community Predict {% if user.is_authenticated %} + History Logout {{user}} {%else%} Login diff --git a/PlanktonDetector/templates/detection_detail.html b/PlanktonDetector/templates/detection_detail.html new file mode 100644 index 0000000..f32f824 --- /dev/null +++ b/PlanktonDetector/templates/detection_detail.html @@ -0,0 +1,7 @@ +{%extends 'base.html'%} +{%load static%} +{%block extracss%} + +{%endblock extracss%} +{%block content%} +{%endblock content%} \ No newline at end of file diff --git a/PlanktonDetector/templates/history.html b/PlanktonDetector/templates/history.html new file mode 100644 index 0000000..91e312e --- /dev/null +++ b/PlanktonDetector/templates/history.html @@ -0,0 +1,40 @@ +{%extends 'base.html'%} +{%load static%} +{%block extracss%} + +{%endblock extracss%} +{%block content%} +
+

History

+ {% for detection in page_obj %} + + {% endfor %} + +
+{%endblock content%} \ No newline at end of file diff --git a/PlanktonDetector/templates/list_posts.html b/PlanktonDetector/templates/list_posts.html new file mode 100644 index 0000000..5ca2d15 --- /dev/null +++ b/PlanktonDetector/templates/list_posts.html @@ -0,0 +1,21 @@ +{%extends 'base.html'%} +{%load static%} +{%block extracss%} + +{%endblock extracss%} +{%block content%} +
+

Posts

+ {% for post in object_list %} +
+ +

{{ post.title }}

+
+

{{post.date_pub}}

+

{{post.author.username}}

+
+
+
+ {% endfor %} +
+{%endblock content%} \ No newline at end of file diff --git a/PlanktonDetector/templates/upload.html b/PlanktonDetector/templates/upload.html index ddd1f57..2a564a1 100644 --- a/PlanktonDetector/templates/upload.html +++ b/PlanktonDetector/templates/upload.html @@ -7,7 +7,10 @@
{% csrf_token %}
- {% if img_saved is None %} + {% if not user.is_authenticated %} +

Please login to submit image

+ + {% elif img_saved is None %}

Choose image for analysis

{% else %} @@ -18,10 +21,10 @@