From 2f8cb24861a274b1b5291eff5c8edb20ccff7794 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 10:34:02 +0300 Subject: [PATCH 01/52] Add new empty app task --- task/__init__.py | 0 task/admin.py | 3 +++ task/apps.py | 6 ++++++ task/migrations/__init__.py | 0 task/models.py | 3 +++ task/tests.py | 3 +++ task/views.py | 3 +++ 7 files changed, 18 insertions(+) create mode 100644 task/__init__.py create mode 100644 task/admin.py create mode 100644 task/apps.py create mode 100644 task/migrations/__init__.py create mode 100644 task/models.py create mode 100644 task/tests.py create mode 100644 task/views.py diff --git a/task/__init__.py b/task/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/task/admin.py b/task/admin.py new file mode 100644 index 0000000..ea5d68b --- /dev/null +++ b/task/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/task/apps.py b/task/apps.py new file mode 100644 index 0000000..5021efc --- /dev/null +++ b/task/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TaskConfig(AppConfig): + default_auto_field = "django.db.models.BigAutoField" + name = "task" diff --git a/task/migrations/__init__.py b/task/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/task/models.py b/task/models.py new file mode 100644 index 0000000..fd18c6e --- /dev/null +++ b/task/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/task/tests.py b/task/tests.py new file mode 100644 index 0000000..de8bdc0 --- /dev/null +++ b/task/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/task/views.py b/task/views.py new file mode 100644 index 0000000..c60c790 --- /dev/null +++ b/task/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From 04c09f3deac04ef2804cb77dc92eac0367ae150e Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 10:36:44 +0300 Subject: [PATCH 02/52] Add task to installed app, change time zone to Europe/Kiev --- to_do_list/settings.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/to_do_list/settings.py b/to_do_list/settings.py index 6ad9676..18d5bf2 100644 --- a/to_do_list/settings.py +++ b/to_do_list/settings.py @@ -37,6 +37,7 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "task", ] MIDDLEWARE = [ @@ -105,7 +106,7 @@ LANGUAGE_CODE = "en-us" -TIME_ZONE = "UTC" +TIME_ZONE = "Europe/Kiev" USE_I18N = True From de83d11cc03a0cbd5164fc1a2ade721371a3a145 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 10:42:56 +0300 Subject: [PATCH 03/52] Add Task model --- task/models.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/task/models.py b/task/models.py index fd18c6e..31a17cd 100644 --- a/task/models.py +++ b/task/models.py @@ -1,3 +1,13 @@ from django.db import models -# Create your models here. + +class Task(models.Model): + content = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + deadline_at = models.DateTimeField(null=True, blank=True) + is_completed = models.BooleanField() + tags = models.ManyToManyField( + to="Tag", + related_name="tasks", + ) + From 57988ba5357d9aaf5b710ea665f318f44fd20bb0 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 10:45:41 +0300 Subject: [PATCH 04/52] Add Tag model --- task/models.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/task/models.py b/task/models.py index 31a17cd..644537c 100644 --- a/task/models.py +++ b/task/models.py @@ -11,3 +11,6 @@ class Task(models.Model): related_name="tasks", ) + +class Tag(models.Model): + name = models.CharField(max_length=255, unique=True) From 169a4c3dcb9f71911b329f2d1ce909adb8867cc0 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 10:47:37 +0300 Subject: [PATCH 05/52] Add migrations for models --- task/migrations/0001_initial.py | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 task/migrations/0001_initial.py diff --git a/task/migrations/0001_initial.py b/task/migrations/0001_initial.py new file mode 100644 index 0000000..5e8f0f7 --- /dev/null +++ b/task/migrations/0001_initial.py @@ -0,0 +1,47 @@ +# Generated by Django 5.1.1 on 2024-09-25 07:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Tag", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255, unique=True)), + ], + ), + migrations.CreateModel( + name="Task", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("content", models.TextField()), + ("created_at", models.DateTimeField(auto_now_add=True)), + ("deadline_at", models.DateTimeField(blank=True, null=True)), + ("is_completed", models.BooleanField()), + ("tags", models.ManyToManyField(related_name="tasks", to="task.tag")), + ], + ), + ] From 310af15187c4f8a08ad20de7d765f85e427772d0 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:05:58 +0300 Subject: [PATCH 06/52] Add urls for the task app --- task/urls.py | 7 +++++++ to_do_list/urls.py | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 task/urls.py diff --git a/task/urls.py b/task/urls.py new file mode 100644 index 0000000..efdcb67 --- /dev/null +++ b/task/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + + +urlpatterns = [ +] + +app_name = "task" diff --git a/to_do_list/urls.py b/to_do_list/urls.py index 5ec9d29..bd646a2 100644 --- a/to_do_list/urls.py +++ b/to_do_list/urls.py @@ -16,8 +16,9 @@ """ from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), + path("", include("task.urls", namespace="task")) ] From 9167f2bb8f9014e4d48bbd0b5bb277f6d8e1b5a4 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:10:17 +0300 Subject: [PATCH 07/52] Add path to index page to task/urls.py --- task/urls.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/task/urls.py b/task/urls.py index efdcb67..d5c734d 100644 --- a/task/urls.py +++ b/task/urls.py @@ -1,7 +1,12 @@ from django.urls import path +from task.views import ( + index, +) + urlpatterns = [ + path("", index, name="index") ] app_name = "task" From 6ff206ad66456d2e4a0de5d6d805691a470a514c Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:10:52 +0300 Subject: [PATCH 08/52] Add empty index view --- task/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/task/views.py b/task/views.py index c60c790..6cb1287 100644 --- a/task/views.py +++ b/task/views.py @@ -1,3 +1,6 @@ +from django.http import HttpRequest, HttpResponse from django.shortcuts import render -# Create your views here. + +def index(request: HttpRequest) -> HttpResponse: + return render(request, "task/index.html") From b89746ed2eb043e330678244e790b6eabc8c2d5a Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:13:36 +0300 Subject: [PATCH 09/52] Add base.html --- templates/base.html | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 templates/base.html diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..1f7b617 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,34 @@ + + + + + {% block title %}TODO list{% endblock %} + + + + + + +
+
+
+ + {% block sidebar %} + {% endblock %} + +
+
+ + {% block content %} + {% endblock %} + + +
+
+
+ + + From 81b8bc96a4263dfe0a8a77799b78fa787bf40176 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:15:38 +0300 Subject: [PATCH 10/52] Add empty index.html template --- templates/task/index.html | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 templates/task/index.html diff --git a/templates/task/index.html b/templates/task/index.html new file mode 100644 index 0000000..7aa0a4c --- /dev/null +++ b/templates/task/index.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} + +{% block content %} + Here will be the content +{% endblock %} From 0c98cb76bf48ed6996a41b14f76bb4af6de91249 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:19:00 +0300 Subject: [PATCH 11/52] Add sidebar.html template to includes --- templates/task/includes/sidebar.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 templates/task/includes/sidebar.html diff --git a/templates/task/includes/sidebar.html b/templates/task/includes/sidebar.html new file mode 100644 index 0000000..df405bf --- /dev/null +++ b/templates/task/includes/sidebar.html @@ -0,0 +1,12 @@ + From 1f0ca6e4c972742520079e896e30c9a4009fd6f6 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:20:03 +0300 Subject: [PATCH 12/52] Include sidebar to base.html --- templates/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/base.html b/templates/base.html index 1f7b617..8cd0e9f 100644 --- a/templates/base.html +++ b/templates/base.html @@ -17,6 +17,7 @@
{% block sidebar %} + {% include "task/includes/sidebar.html" %} {% endblock %}
From 9844322551cbeda787df7f341cda062216555f53 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:25:30 +0300 Subject: [PATCH 13/52] Register Task and Tag models to admin panel --- task/admin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/task/admin.py b/task/admin.py index ea5d68b..3368e99 100644 --- a/task/admin.py +++ b/task/admin.py @@ -1,3 +1,7 @@ from django.contrib import admin -# Register your models here. +from task.models import Task, Tag + + +admin.site.register(Task) +admin.site.register(Tag) From cf22f17637db84aefa40c40d64c914741dfcd3c4 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:28:00 +0300 Subject: [PATCH 14/52] Alter content field for Task model, name field for Tag model, add new migration file --- .../0002_alter_tag_name_alter_task_content.py | 23 +++++++++++++++++++ task/models.py | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 task/migrations/0002_alter_tag_name_alter_task_content.py diff --git a/task/migrations/0002_alter_tag_name_alter_task_content.py b/task/migrations/0002_alter_tag_name_alter_task_content.py new file mode 100644 index 0000000..9a660a3 --- /dev/null +++ b/task/migrations/0002_alter_tag_name_alter_task_content.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.1 on 2024-09-25 08:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0001_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="tag", + name="name", + field=models.CharField(max_length=23, unique=True), + ), + migrations.AlterField( + model_name="task", + name="content", + field=models.CharField(max_length=255), + ), + ] diff --git a/task/models.py b/task/models.py index 644537c..6d362ba 100644 --- a/task/models.py +++ b/task/models.py @@ -2,7 +2,7 @@ class Task(models.Model): - content = models.TextField() + content = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) deadline_at = models.DateTimeField(null=True, blank=True) is_completed = models.BooleanField() @@ -13,4 +13,4 @@ class Task(models.Model): class Tag(models.Model): - name = models.CharField(max_length=255, unique=True) + name = models.CharField(max_length=23, unique=True) From f780f9deb58afe096d9243a3fa6d21410395ddf1 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:29:14 +0300 Subject: [PATCH 15/52] Add str method for Task & Tag models --- task/models.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/task/models.py b/task/models.py index 6d362ba..b079d95 100644 --- a/task/models.py +++ b/task/models.py @@ -11,6 +11,11 @@ class Task(models.Model): related_name="tasks", ) + def __str__(self) -> str: + return self.content class Tag(models.Model): name = models.CharField(max_length=23, unique=True) + + def __str__(self) -> str: + return self.name From bef83e8e404cd5b06f0e9ff77ab8a1db41509512 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:40:02 +0300 Subject: [PATCH 16/52] Add django-debug-toolbar for development purposes --- to_do_list/settings.py | 6 ++++++ to_do_list/urls.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/to_do_list/settings.py b/to_do_list/settings.py index 18d5bf2..40c8d4b 100644 --- a/to_do_list/settings.py +++ b/to_do_list/settings.py @@ -37,11 +37,13 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "debug_toolbar", "task", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "debug_toolbar.middleware.DebugToolbarMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -118,6 +120,10 @@ STATIC_URL = "static/" +INTERNAL_IPS = [ + "127.0.0.1", +] + # Default primary key field type # https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field diff --git a/to_do_list/urls.py b/to_do_list/urls.py index bd646a2..565ee43 100644 --- a/to_do_list/urls.py +++ b/to_do_list/urls.py @@ -14,11 +14,11 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ - +from debug_toolbar.toolbar import debug_toolbar_urls from django.contrib import admin from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), path("", include("task.urls", namespace="task")) -] +] + debug_toolbar_urls() From f31d4d25160b100cc0f01db2265bdd01b27c4628 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:40:30 +0300 Subject: [PATCH 17/52] Add django-debug-toolbar to requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index b655ece..76fda35 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ black==24.8.0 click==8.1.7 colorama==0.4.6 Django==5.1.1 +django-debug-toolbar==4.4.6 mypy-extensions==1.0.0 packaging==24.1 pathspec==0.12.1 From 0439585982edefc456fcf0b2cb2dad85292608f1 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:44:53 +0300 Subject: [PATCH 18/52] Add static files setting and empty styles.css --- static/css/styles.css | 0 to_do_list/settings.py | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 static/css/styles.css diff --git a/static/css/styles.css b/static/css/styles.css new file mode 100644 index 0000000..e69de29 diff --git a/to_do_list/settings.py b/to_do_list/settings.py index 40c8d4b..90675b6 100644 --- a/to_do_list/settings.py +++ b/to_do_list/settings.py @@ -120,6 +120,10 @@ STATIC_URL = "static/" +STATICFILES_DIRS = [ + BASE_DIR / "static", +] + INTERNAL_IPS = [ "127.0.0.1", ] From d96b62ec2b598ec49478a1bfea2df4738925210f Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 11:47:41 +0300 Subject: [PATCH 19/52] Fix margin for body in html templates --- static/css/styles.css | 3 +++ templates/base.html | 2 ++ 2 files changed, 5 insertions(+) diff --git a/static/css/styles.css b/static/css/styles.css index e69de29..7a063f3 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -0,0 +1,3 @@ +body { + margin-top: 20px; +} diff --git a/templates/base.html b/templates/base.html index 8cd0e9f..eeb233e 100644 --- a/templates/base.html +++ b/templates/base.html @@ -9,6 +9,8 @@ href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> + {% load static %} + From 074146421bf4d27a43446452b24ef835982da5df Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 12:44:35 +0300 Subject: [PATCH 20/52] Alter tags field for task making it not required, edit index.html" --- task/migrations/0003_alter_task_tags.py | 20 +++++++++ task/migrations/0004_alter_task_tags.py | 20 +++++++++ task/models.py | 2 + task/views.py | 8 +++- templates/task/index.html | 59 ++++++++++++++++++++++++- 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 task/migrations/0003_alter_task_tags.py create mode 100644 task/migrations/0004_alter_task_tags.py diff --git a/task/migrations/0003_alter_task_tags.py b/task/migrations/0003_alter_task_tags.py new file mode 100644 index 0000000..89fc648 --- /dev/null +++ b/task/migrations/0003_alter_task_tags.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.1 on 2024-09-25 09:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0002_alter_tag_name_alter_task_content"), + ] + + operations = [ + migrations.AlterField( + model_name="task", + name="tags", + field=models.ManyToManyField( + null=True, related_name="tasks", to="task.tag" + ), + ), + ] diff --git a/task/migrations/0004_alter_task_tags.py b/task/migrations/0004_alter_task_tags.py new file mode 100644 index 0000000..49225e8 --- /dev/null +++ b/task/migrations/0004_alter_task_tags.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.1 on 2024-09-25 09:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0003_alter_task_tags"), + ] + + operations = [ + migrations.AlterField( + model_name="task", + name="tags", + field=models.ManyToManyField( + blank=True, null=True, related_name="tasks", to="task.tag" + ), + ), + ] diff --git a/task/models.py b/task/models.py index b079d95..d232185 100644 --- a/task/models.py +++ b/task/models.py @@ -9,6 +9,8 @@ class Task(models.Model): tags = models.ManyToManyField( to="Tag", related_name="tasks", + null=True, + blank=True, ) def __str__(self) -> str: diff --git a/task/views.py b/task/views.py index 6cb1287..cf5aec9 100644 --- a/task/views.py +++ b/task/views.py @@ -1,6 +1,12 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render +from task.models import Task + def index(request: HttpRequest) -> HttpResponse: - return render(request, "task/index.html") + tasks = Task.objects.all() + context = { + "tasks": tasks + } + return render(request, "task/index.html", context=context) diff --git a/templates/task/index.html b/templates/task/index.html index 7aa0a4c..2e5ec0d 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -1,5 +1,62 @@ {% extends "base.html" %} {% block content %} - Here will be the content +

TODO list

+ {% if tasks %} + {% for task in tasks %} +
+
+ +
+
+
+

+ {{ task }} +

+ {% if task.is_completed %} +

+ Done +

+ {% else %} +

+ Not done +

+ {% endif %} + +
+
+ Complete button +
+
+ +
+ +
+

+ Created at: {{ task.created_at }} +

+ {% if task.deadline_at %} +

+ Deadline: {{ task.deadline_at }} +

+ {% endif %} +
+ +
+
+

Tags:

+ {% for tag in task.tags.all %} + {{ tag }} + {% empty %} +

No tags

+ {% endfor %} +
+
+ +
+
+ {% endfor %} + {% else %} + No tasks yet. Create a new one. + {% endif %} {% endblock %} From 0afec447765986a20be7768071b7372678b56ef9 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 12:48:11 +0300 Subject: [PATCH 21/52] Fix index.html, fix N+1 problem --- task/views.py | 2 +- templates/task/index.html | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/task/views.py b/task/views.py index cf5aec9..c9c7956 100644 --- a/task/views.py +++ b/task/views.py @@ -5,7 +5,7 @@ def index(request: HttpRequest) -> HttpResponse: - tasks = Task.objects.all() + tasks = Task.objects.prefetch_related("tags") context = { "tasks": tasks } diff --git a/templates/task/index.html b/templates/task/index.html index 2e5ec0d..58b2558 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -44,11 +44,11 @@

TODO list

-

Tags:

+

Tags:

{% for tag in task.tags.all %} - {{ tag }} +

#{{ tag }}

{% empty %} -

No tags

+

No tags

{% endfor %}
From 752013989f582397c04dd60fff6f765834f596bf Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 12:51:48 +0300 Subject: [PATCH 22/52] Add ordering for tasks in meta class --- task/migrations/0005_alter_task_options.py | 17 +++++++++++++++++ task/models.py | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 task/migrations/0005_alter_task_options.py diff --git a/task/migrations/0005_alter_task_options.py b/task/migrations/0005_alter_task_options.py new file mode 100644 index 0000000..a0a65e1 --- /dev/null +++ b/task/migrations/0005_alter_task_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.1 on 2024-09-25 09:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0004_alter_task_tags"), + ] + + operations = [ + migrations.AlterModelOptions( + name="task", + options={"ordering": ("is_completed", "-created_at")}, + ), + ] diff --git a/task/models.py b/task/models.py index d232185..f3e0eeb 100644 --- a/task/models.py +++ b/task/models.py @@ -13,6 +13,13 @@ class Task(models.Model): blank=True, ) + class Meta: + ordering = ( + "is_completed", + "-created_at", + ) + + def __str__(self) -> str: return self.content From cbd7ea23425b9f99567df689673be1945677ff2d Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 12:57:03 +0300 Subject: [PATCH 23/52] Add task create view and endpoint --- task/urls.py | 4 +++- task/views.py | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/task/urls.py b/task/urls.py index d5c734d..3f55641 100644 --- a/task/urls.py +++ b/task/urls.py @@ -2,11 +2,13 @@ from task.views import ( index, + TaskCreateView, ) urlpatterns = [ - path("", index, name="index") + path("", index, name="index"), + path("tasks/create/", TaskCreateView.as_view(), name="task-create"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index c9c7956..89d7609 100644 --- a/task/views.py +++ b/task/views.py @@ -1,5 +1,7 @@ from django.http import HttpRequest, HttpResponse from django.shortcuts import render +from django.urls import reverse_lazy +from django.views import generic from task.models import Task @@ -10,3 +12,9 @@ def index(request: HttpRequest) -> HttpResponse: "tasks": tasks } return render(request, "task/index.html", context=context) + + +class TaskCreateView(generic.CreateView): + model = Task + fields = "__all__" + success_url = reverse_lazy("task:index") From 700d3639db8f2d73848e3988aadcac9826e9763d Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:06:04 +0300 Subject: [PATCH 24/52] Add cripsy forms to installed apps --- to_do_list/settings.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/to_do_list/settings.py b/to_do_list/settings.py index 90675b6..6ac2435 100644 --- a/to_do_list/settings.py +++ b/to_do_list/settings.py @@ -37,6 +37,8 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "crispy_forms", + "crispy_bootstrap5", "debug_toolbar", "task", ] @@ -132,3 +134,9 @@ # https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +# Django crispy forms settings + +CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" + +CRISPY_TEMPLATE_PACK = "bootstrap5" From 0b1ba73c97dacd3a9b43a6f669a24d86951a60d9 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:06:50 +0300 Subject: [PATCH 25/52] Add cripsy forms to requirements.txt --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 76fda35..8017394 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,9 @@ asgiref==3.8.1 black==24.8.0 click==8.1.7 colorama==0.4.6 +crispy-bootstrap5==2024.2 Django==5.1.1 +django-crispy-forms==2.3 django-debug-toolbar==4.4.6 mypy-extensions==1.0.0 packaging==24.1 From cc6426d356179f3375d4aec6ddad9a1410a2fa39 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:07:40 +0300 Subject: [PATCH 26/52] Add Task create view and task form template --- task/views.py | 2 +- templates/base.html | 2 +- templates/{task => }/includes/sidebar.html | 0 templates/task/task_form.html | 12 ++++++++++++ 4 files changed, 14 insertions(+), 2 deletions(-) rename templates/{task => }/includes/sidebar.html (100%) create mode 100644 templates/task/task_form.html diff --git a/task/views.py b/task/views.py index 89d7609..f7ddc27 100644 --- a/task/views.py +++ b/task/views.py @@ -16,5 +16,5 @@ def index(request: HttpRequest) -> HttpResponse: class TaskCreateView(generic.CreateView): model = Task - fields = "__all__" + fields = ("content", "deadline_at", "tags") success_url = reverse_lazy("task:index") diff --git a/templates/base.html b/templates/base.html index eeb233e..7f38b30 100644 --- a/templates/base.html +++ b/templates/base.html @@ -19,7 +19,7 @@
{% block sidebar %} - {% include "task/includes/sidebar.html" %} + {% include "includes/sidebar.html" %} {% endblock %}
diff --git a/templates/task/includes/sidebar.html b/templates/includes/sidebar.html similarity index 100% rename from templates/task/includes/sidebar.html rename to templates/includes/sidebar.html diff --git a/templates/task/task_form.html b/templates/task/task_form.html new file mode 100644 index 0000000..133f063 --- /dev/null +++ b/templates/task/task_form.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} + +{% block content %} +

{{ object|yesno:"Update,Create" }} task

+
+ {% csrf_token %} + {{ form|crispy }} + + +
+{% endblock %} \ No newline at end of file From f218b7a243a29c66dd4138b2a088fde913953122 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:10:19 +0300 Subject: [PATCH 27/52] Add 'create new task' button --- templates/task/index.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/templates/task/index.html b/templates/task/index.html index 58b2558..702bb4a 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -1,7 +1,13 @@ {% extends "base.html" %} {% block content %} -

TODO list

+
+

TODO list

+ + Add a new task + +
+ {% if tasks %} {% for task in tasks %}
From c0268ac12a9ba2d0fcc8f746bc4a6041e11afe60 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:18:11 +0300 Subject: [PATCH 28/52] Add empty forms.py file --- task/forms.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 task/forms.py diff --git a/task/forms.py b/task/forms.py new file mode 100644 index 0000000..e69de29 From a9df1880cc8ab7bc3016efa684f43b7fa8311247 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:19:04 +0300 Subject: [PATCH 29/52] Add default value for is_coompleted field for Task model --- .../migrations/0006_alter_task_is_completed.py | 18 ++++++++++++++++++ task/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 task/migrations/0006_alter_task_is_completed.py diff --git a/task/migrations/0006_alter_task_is_completed.py b/task/migrations/0006_alter_task_is_completed.py new file mode 100644 index 0000000..1f901bb --- /dev/null +++ b/task/migrations/0006_alter_task_is_completed.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-25 10:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0005_alter_task_options"), + ] + + operations = [ + migrations.AlterField( + model_name="task", + name="is_completed", + field=models.BooleanField(default=False), + ), + ] diff --git a/task/models.py b/task/models.py index f3e0eeb..d9e1f9a 100644 --- a/task/models.py +++ b/task/models.py @@ -5,7 +5,7 @@ class Task(models.Model): content = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) deadline_at = models.DateTimeField(null=True, blank=True) - is_completed = models.BooleanField() + is_completed = models.BooleanField(default=False) tags = models.ManyToManyField( to="Tag", related_name="tasks", From 73d79318eb84288a2fa5819c2c1dea79b47d0f7f Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:19:50 +0300 Subject: [PATCH 30/52] Add Task form to forms.py, edit Task create view --- task/forms.py | 24 ++++++++++++++++++++++++ task/views.py | 3 ++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/task/forms.py b/task/forms.py index e69de29..946c014 100644 --- a/task/forms.py +++ b/task/forms.py @@ -0,0 +1,24 @@ +from django import forms + +from task.models import Tag, Task + + +class TaskForm(forms.ModelForm): + tags = forms.ModelMultipleChoiceField( + queryset=Tag.objects.all(), + widget=forms.CheckboxSelectMultiple, + required=False, + ) + + deadline_at = forms.DateTimeField( + widget=forms.DateTimeInput(attrs={"type": "datetime-local"}), + required=False + ) + + class Meta: + model = Task + fields = ( + "content", + "deadline_at", + "tags" + ) diff --git a/task/views.py b/task/views.py index f7ddc27..1139525 100644 --- a/task/views.py +++ b/task/views.py @@ -3,6 +3,7 @@ from django.urls import reverse_lazy from django.views import generic +from task.forms import TaskForm from task.models import Task @@ -16,5 +17,5 @@ def index(request: HttpRequest) -> HttpResponse: class TaskCreateView(generic.CreateView): model = Task - fields = ("content", "deadline_at", "tags") + form_class = TaskForm success_url = reverse_lazy("task:index") From e962c9b4c1fb368429301ffe31ee376da8b7daea Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:23:26 +0300 Subject: [PATCH 31/52] Add Task update view and update path to urls.py --- task/urls.py | 2 ++ task/views.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/task/urls.py b/task/urls.py index 3f55641..43422a3 100644 --- a/task/urls.py +++ b/task/urls.py @@ -3,12 +3,14 @@ from task.views import ( index, TaskCreateView, + TaskUpdateView, ) urlpatterns = [ path("", index, name="index"), path("tasks/create/", TaskCreateView.as_view(), name="task-create"), + path("tasks//update/", TaskUpdateView.as_view(), name="task-update"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index 1139525..58446b5 100644 --- a/task/views.py +++ b/task/views.py @@ -19,3 +19,9 @@ class TaskCreateView(generic.CreateView): model = Task form_class = TaskForm success_url = reverse_lazy("task:index") + + +class TaskUpdateView(generic.UpdateView): + model = Task + form_class = TaskForm + success_url = reverse_lazy("task:index") From 1524e97a197487a2de4698d12f61dbe9080efc6f Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:27:50 +0300 Subject: [PATCH 32/52] Add Task delete view and path to urls.py --- task/urls.py | 2 ++ task/views.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/task/urls.py b/task/urls.py index 43422a3..b8ce379 100644 --- a/task/urls.py +++ b/task/urls.py @@ -4,6 +4,7 @@ index, TaskCreateView, TaskUpdateView, + TaskDeleteView, ) @@ -11,6 +12,7 @@ path("", index, name="index"), path("tasks/create/", TaskCreateView.as_view(), name="task-create"), path("tasks//update/", TaskUpdateView.as_view(), name="task-update"), + path("tasks//delete/", TaskDeleteView.as_view(), name="task-delete"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index 58446b5..a378ce7 100644 --- a/task/views.py +++ b/task/views.py @@ -25,3 +25,7 @@ class TaskUpdateView(generic.UpdateView): model = Task form_class = TaskForm success_url = reverse_lazy("task:index") + +class TaskDeleteView(generic.DeleteView): + model = Task + success_url = reverse_lazy("task:index") From 95aff30c1c09d099fff8328cc4bd9cdfffa5fbb7 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:28:13 +0300 Subject: [PATCH 33/52] Add Task confirm delete template --- templates/task/task_confirm_delete.html | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 templates/task/task_confirm_delete.html diff --git a/templates/task/task_confirm_delete.html b/templates/task/task_confirm_delete.html new file mode 100644 index 0000000..b8a979a --- /dev/null +++ b/templates/task/task_confirm_delete.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block content %} +

Delete task: {{ task }}?

+
+ {% csrf_token %} + Cancel + +
+{% endblock %} From da78859818ff8f4e3fe0f9e65a562fb6d9e3e5b9 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:36:23 +0300 Subject: [PATCH 34/52] Add update and delete buttons to each task --- templates/task/index.html | 85 ++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/templates/task/index.html b/templates/task/index.html index 702bb4a..dfc01be 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -11,52 +11,61 @@

TODO list

{% if tasks %} {% for task in tasks %}
-
+
-
-
-
-

- {{ task }} +

+
+
+

+ {{ task }} +

+ {% if task.is_completed %} +

+ Done +

+ {% else %} +

+ Not done

- {% if task.is_completed %} -

- Done -

- {% else %} -

- Not done -

- {% endif %} + {% endif %} -
-
- Complete button -
- +
+ Complete button +
-
-

- Created at: {{ task.created_at }} +

+ +
+

+ Created at: {{ task.created_at }} +

+ {% if task.deadline_at %} +

+ Deadline: {{ task.deadline_at }}

- {% if task.deadline_at %} -

- Deadline: {{ task.deadline_at }} -

- {% endif %} -
+ {% endif %} +
-
-
-

Tags:

- {% for tag in task.tags.all %} -

#{{ tag }}

- {% empty %} -

No tags

- {% endfor %} -
+
+
+

Tags:

+ {% for tag in task.tags.all %} +

#{{ tag }}

+ {% empty %} +

No tags

+ {% endfor %} +
+
From 647e474870ca8f1e24dbdf54e7c75d030c18dae6 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:47:53 +0300 Subject: [PATCH 35/52] Add complete and undo buttons to each task, change index view --- task/views.py | 11 ++++++++++- templates/task/index.html | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/task/views.py b/task/views.py index a378ce7..833d06b 100644 --- a/task/views.py +++ b/task/views.py @@ -1,5 +1,5 @@ from django.http import HttpRequest, HttpResponse -from django.shortcuts import render +from django.shortcuts import render, get_object_or_404, redirect from django.urls import reverse_lazy from django.views import generic @@ -8,6 +8,15 @@ def index(request: HttpRequest) -> HttpResponse: + if request.method == "POST": + task_id = request.POST.get("task_id") + task = get_object_or_404(Task, id=task_id) + if task.is_completed: + task.is_completed = False + else: + task.is_completed = True + task.save() + return redirect("task:index") tasks = Task.objects.prefetch_related("tags") context = { "tasks": tasks diff --git a/templates/task/index.html b/templates/task/index.html index dfc01be..571767a 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -31,7 +31,21 @@

TODO list

- Complete button +
+ {% csrf_token %} + + {% if task.is_completed %} + + {% else %} + + {% endif %} + + +
From f75f17cc2f62a0b2013ecc3d612e02ad9d40db8a Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 13:57:48 +0300 Subject: [PATCH 36/52] Edit css style for index.html --- static/css/styles.css | 8 ++++++++ templates/task/index.html | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/static/css/styles.css b/static/css/styles.css index 7a063f3..452fd97 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -1,3 +1,11 @@ body { margin-top: 20px; } + +.task { + transition: background-color 0.3s ease; +} + +.task:hover { + background-color: ghostwhite; +} \ No newline at end of file diff --git a/templates/task/index.html b/templates/task/index.html index 571767a..ead8f80 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -11,7 +11,7 @@

TODO list

{% if tasks %} {% for task in tasks %}
-
+
@@ -43,7 +43,7 @@

TODO list

Complete {% endif %} - +
From 6751f815bb81230b8dd5596d301467f6a4442f5b Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:00:29 +0300 Subject: [PATCH 37/52] Add Tag list view and path to urls.py --- task/urls.py | 2 ++ task/views.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/task/urls.py b/task/urls.py index b8ce379..07191ad 100644 --- a/task/urls.py +++ b/task/urls.py @@ -5,6 +5,7 @@ TaskCreateView, TaskUpdateView, TaskDeleteView, + TagListView, ) @@ -13,6 +14,7 @@ path("tasks/create/", TaskCreateView.as_view(), name="task-create"), path("tasks//update/", TaskUpdateView.as_view(), name="task-update"), path("tasks//delete/", TaskDeleteView.as_view(), name="task-delete"), + path("tags/", TagListView.as_view(), name="tag-list"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index 833d06b..2689727 100644 --- a/task/views.py +++ b/task/views.py @@ -4,7 +4,7 @@ from django.views import generic from task.forms import TaskForm -from task.models import Task +from task.models import Task, Tag def index(request: HttpRequest) -> HttpResponse: @@ -35,6 +35,11 @@ class TaskUpdateView(generic.UpdateView): form_class = TaskForm success_url = reverse_lazy("task:index") + class TaskDeleteView(generic.DeleteView): model = Task success_url = reverse_lazy("task:index") + +class TagListView(generic.ListView): + model = Tag + From 05125566ab321fdca76932261eedd3f05b71ad1e Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:06:01 +0300 Subject: [PATCH 38/52] Add bootstrap icons --- templates/base.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/templates/base.html b/templates/base.html index 7f38b30..fd56d4d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,9 +6,11 @@ + href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" + integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" + crossorigin="anonymous"> + {% load static %} From 82bb035cf4ada556a9b1e7bc2cfda815aaa5416b Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:06:21 +0300 Subject: [PATCH 39/52] Add Tag list template --- templates/task/tag_list.html | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 templates/task/tag_list.html diff --git a/templates/task/tag_list.html b/templates/task/tag_list.html new file mode 100644 index 0000000..b189d43 --- /dev/null +++ b/templates/task/tag_list.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} + +{% block content %} +
+

Tag list

+ + Add a new tag + +
+ {% if tag_list %} + + + + + + + {% for tag in tag_list %} + + + + + + {% endfor %} +
NameUpdateDelete
{{ tag.name }} + + + + + + + +
+ {% else %} +

There are no tags.

+ {% endif %} +{% endblock %} + From e3c61e4be9b3b66d742d626d5e1226188927ddc3 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:07:14 +0300 Subject: [PATCH 40/52] Add link to the tags page to the sidebar --- templates/includes/sidebar.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/includes/sidebar.html b/templates/includes/sidebar.html index df405bf..b3558c9 100644 --- a/templates/includes/sidebar.html +++ b/templates/includes/sidebar.html @@ -5,7 +5,7 @@
  • - + Tags
  • From 0cb72d602fe7a4f4a24c65fd868175c3d4280061 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:09:26 +0300 Subject: [PATCH 41/52] Add Tag create view, add path to tag create view in urls.py --- task/urls.py | 2 ++ task/views.py | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/task/urls.py b/task/urls.py index 07191ad..895b87a 100644 --- a/task/urls.py +++ b/task/urls.py @@ -6,6 +6,7 @@ TaskUpdateView, TaskDeleteView, TagListView, + TagCreateView, ) @@ -15,6 +16,7 @@ path("tasks//update/", TaskUpdateView.as_view(), name="task-update"), path("tasks//delete/", TaskDeleteView.as_view(), name="task-delete"), path("tags/", TagListView.as_view(), name="tag-list"), + path("tags/create/", TagCreateView.as_view(), name="tag-create"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index 2689727..77f3e30 100644 --- a/task/views.py +++ b/task/views.py @@ -40,6 +40,11 @@ class TaskDeleteView(generic.DeleteView): model = Task success_url = reverse_lazy("task:index") + class TagListView(generic.ListView): model = Tag + +class TagCreateView(generic.CreateView): + model = Tag + fields = "__all__" From 0ef58ce7e8375967e2a3003b899cbae062304194 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:12:40 +0300 Subject: [PATCH 42/52] Add tag form template, add link to add new tag to tag list template --- task/views.py | 1 + templates/task/tag_list.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/task/views.py b/task/views.py index 77f3e30..a19f3d3 100644 --- a/task/views.py +++ b/task/views.py @@ -48,3 +48,4 @@ class TagListView(generic.ListView): class TagCreateView(generic.CreateView): model = Tag fields = "__all__" + success_url = reverse_lazy("task:tag-list") diff --git a/templates/task/tag_list.html b/templates/task/tag_list.html index b189d43..dfecdc7 100644 --- a/templates/task/tag_list.html +++ b/templates/task/tag_list.html @@ -3,7 +3,7 @@ {% block content %} From b405f8304ee39c03d99e1b29a79fc353e562f1bd Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:13:07 +0300 Subject: [PATCH 43/52] Edit tag form template --- templates/task/tag_form.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 templates/task/tag_form.html diff --git a/templates/task/tag_form.html b/templates/task/tag_form.html new file mode 100644 index 0000000..0100df3 --- /dev/null +++ b/templates/task/tag_form.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} +{% load crispy_forms_filters %} + +{% block content %} +

    {{ object|yesno:"Update,Create" }} tag

    +
    + {% csrf_token %} + {{ form|crispy }} + +
    +{% endblock %} From 0db6ef6606015098ef70015436cc32b180a616bc Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:15:40 +0300 Subject: [PATCH 44/52] Add Tag update view, add the link to tag list --- task/urls.py | 2 ++ task/views.py | 6 ++++++ templates/task/tag_list.html | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/task/urls.py b/task/urls.py index 895b87a..120f405 100644 --- a/task/urls.py +++ b/task/urls.py @@ -7,6 +7,7 @@ TaskDeleteView, TagListView, TagCreateView, + TagUpdateView, ) @@ -17,6 +18,7 @@ path("tasks//delete/", TaskDeleteView.as_view(), name="task-delete"), path("tags/", TagListView.as_view(), name="tag-list"), path("tags/create/", TagCreateView.as_view(), name="tag-create"), + path("tags//update/", TagUpdateView.as_view(), name="tag-update"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index a19f3d3..3a805a7 100644 --- a/task/views.py +++ b/task/views.py @@ -49,3 +49,9 @@ class TagCreateView(generic.CreateView): model = Tag fields = "__all__" success_url = reverse_lazy("task:tag-list") + + +class TagUpdateView(generic.UpdateView): + model = Tag + fields = "__all__" + success_url = reverse_lazy("task:tag-list") diff --git a/templates/task/tag_list.html b/templates/task/tag_list.html index dfecdc7..695e240 100644 --- a/templates/task/tag_list.html +++ b/templates/task/tag_list.html @@ -18,7 +18,7 @@

    Tag list

    {{ tag.name }} - + From 0409ad4b7d9297a84d3502c28899ad076e53ad02 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:18:25 +0300 Subject: [PATCH 45/52] Add Tag delete view, add path to urls.py, add link to tag list template --- task/urls.py | 2 ++ task/views.py | 5 +++++ templates/task/tag_list.html | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/task/urls.py b/task/urls.py index 120f405..fb5adb4 100644 --- a/task/urls.py +++ b/task/urls.py @@ -8,6 +8,7 @@ TagListView, TagCreateView, TagUpdateView, + TagDeleteView, ) @@ -19,6 +20,7 @@ path("tags/", TagListView.as_view(), name="tag-list"), path("tags/create/", TagCreateView.as_view(), name="tag-create"), path("tags//update/", TagUpdateView.as_view(), name="tag-update"), + path("tags//delete/", TagDeleteView.as_view(), name="tag-delete"), ] app_name = "task" diff --git a/task/views.py b/task/views.py index 3a805a7..e5538af 100644 --- a/task/views.py +++ b/task/views.py @@ -55,3 +55,8 @@ class TagUpdateView(generic.UpdateView): model = Tag fields = "__all__" success_url = reverse_lazy("task:tag-list") + + +class TagDeleteView(generic.DeleteView): + model = Tag + success_url = reverse_lazy("task:tag-list") diff --git a/templates/task/tag_list.html b/templates/task/tag_list.html index 695e240..03ceffc 100644 --- a/templates/task/tag_list.html +++ b/templates/task/tag_list.html @@ -24,7 +24,7 @@

    Tag list

    + href="{% url 'task:tag-delete' tag.id %}"> From 79ef33371cdf9e8bc2c5797334022e2cc9a48a13 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:18:59 +0300 Subject: [PATCH 46/52] Add Tag confirm delete template --- templates/task/tag_confirm_delete.html | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 templates/task/tag_confirm_delete.html diff --git a/templates/task/tag_confirm_delete.html b/templates/task/tag_confirm_delete.html new file mode 100644 index 0000000..2d9ec4e --- /dev/null +++ b/templates/task/tag_confirm_delete.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block content %} +

    Delete tag: {{ tag }}?

    +
    + {% csrf_token %} + Cancel + +
    +{% endblock %} From 3e8b75c86c550536c706f2360f0c728414cfd508 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:27:38 +0300 Subject: [PATCH 47/52] Add icons instead of buttons for task deletion/updating --- templates/task/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/task/index.html b/templates/task/index.html index ead8f80..576a99f 100644 --- a/templates/task/index.html +++ b/templates/task/index.html @@ -74,11 +74,11 @@

    TODO list

    From 2b47e1807d2d2798525fa7bb988fd4f281dc6a7c Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:33:22 +0300 Subject: [PATCH 48/52] Write README.md --- README.md | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c20690c..ac3d1ca 100644 --- a/README.md +++ b/README.md @@ -1 +1,52 @@ -# TODO list +# TODO list 📝 + +# Shop Wise 🛒 + +This is a Django-based web application for managing tasks. + +## Installation + +Python3 must be already installed. + +1. **Clone the repository:** + ```bash + git clone https://github.com/vladislav-tsybuliak1/todo-list.git + cd django-todo-list + ``` + +2. **Create a virtual environment and activate it:** + ```bash + python -m venv env + source env/bin/activate # On Windows use `env\Scripts\activate` + ``` + +3. **Install the dependencies:** + ```bash + pip install -r requirements.txt + ``` + +4. **Apply the migrations:** + ```bash + python manage.py migrate + ``` + +5. **Create a superuser:** + ```bash + python manage.py createsuperuser + ``` + +6. **Run the development server:** + ```bash + python manage.py runserver + ``` + +## Features + +- Task listing, creation, update, and deletion +- Tag listing, creation, update, and deletion +- Managing tasks by completing them + +## Contact + +For any inquiries, please contact [vladislav.tsybuliak@gmail.com](mailto:vladislav.tsybuliak@gmail.com). + From 81d71b745aed69d6cf241b85428101d307cd8917 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:36:11 +0300 Subject: [PATCH 49/52] Add flake8 to requirements.txt --- requirements.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/requirements.txt b/requirements.txt index 8017394..c850598 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,9 +6,13 @@ crispy-bootstrap5==2024.2 Django==5.1.1 django-crispy-forms==2.3 django-debug-toolbar==4.4.6 +flake8==7.1.1 +mccabe==0.7.0 mypy-extensions==1.0.0 packaging==24.1 pathspec==0.12.1 platformdirs==4.3.6 +pycodestyle==2.12.1 +pyflakes==3.2.0 sqlparse==0.5.1 tzdata==2024.2 From 86a3513aa54142c0f6f3e1e34ea2f73a30d5e4b3 Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Wed, 25 Sep 2024 14:38:51 +0300 Subject: [PATCH 50/52] Fix style by PEP8, fix .html files style --- task/models.py | 2 +- task/urls.py | 12 ++++++++++-- templates/base.html | 7 ++++--- templates/task/tag_list.html | 9 ++++----- templates/task/task_form.html | 2 +- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/task/models.py b/task/models.py index d9e1f9a..210d7ce 100644 --- a/task/models.py +++ b/task/models.py @@ -19,10 +19,10 @@ class Meta: "-created_at", ) - def __str__(self) -> str: return self.content + class Tag(models.Model): name = models.CharField(max_length=23, unique=True) diff --git a/task/urls.py b/task/urls.py index fb5adb4..88e2ebc 100644 --- a/task/urls.py +++ b/task/urls.py @@ -15,8 +15,16 @@ urlpatterns = [ path("", index, name="index"), path("tasks/create/", TaskCreateView.as_view(), name="task-create"), - path("tasks//update/", TaskUpdateView.as_view(), name="task-update"), - path("tasks//delete/", TaskDeleteView.as_view(), name="task-delete"), + path( + "tasks//update/", + TaskUpdateView.as_view(), + name="task-update" + ), + path( + "tasks//delete/", + TaskDeleteView.as_view(), + name="task-delete" + ), path("tags/", TagListView.as_view(), name="tag-list"), path("tags/create/", TagCreateView.as_view(), name="tag-create"), path("tags//update/", TagUpdateView.as_view(), name="tag-update"), diff --git a/templates/base.html b/templates/base.html index fd56d4d..acdef2c 100644 --- a/templates/base.html +++ b/templates/base.html @@ -9,8 +9,10 @@ href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous"> - + {% load static %} @@ -29,7 +31,6 @@ {% block content %} {% endblock %} -
    diff --git a/templates/task/tag_list.html b/templates/task/tag_list.html index 03ceffc..de46d8c 100644 --- a/templates/task/tag_list.html +++ b/templates/task/tag_list.html @@ -3,9 +3,9 @@ {% block content %} {% if tag_list %} @@ -27,7 +27,7 @@

    Tag list

    href="{% url 'task:tag-delete' tag.id %}"> - + {% endfor %}
    @@ -35,4 +35,3 @@

    Tag list

    There are no tags.

    {% endif %} {% endblock %} - diff --git a/templates/task/task_form.html b/templates/task/task_form.html index 133f063..acf919c 100644 --- a/templates/task/task_form.html +++ b/templates/task/task_form.html @@ -9,4 +9,4 @@

    {{ object|yesno:"Update,Create" }} task

    -{% endblock %} \ No newline at end of file +{% endblock %} From 5425857830c36f9db2fb9def7435b11a06742f6f Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Sat, 28 Sep 2024 20:14:38 +0300 Subject: [PATCH 51/52] Fix comments --- static/css/styles.css | 2 +- task/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/css/styles.css b/static/css/styles.css index 452fd97..5cb9497 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -8,4 +8,4 @@ body { .task:hover { background-color: ghostwhite; -} \ No newline at end of file +} diff --git a/task/models.py b/task/models.py index 210d7ce..c4c4f6f 100644 --- a/task/models.py +++ b/task/models.py @@ -24,7 +24,7 @@ def __str__(self) -> str: class Tag(models.Model): - name = models.CharField(max_length=23, unique=True) + name = models.CharField(max_length=63, unique=True) def __str__(self) -> str: return self.name From b3dd9bca88a1693d4280b3def841a445c71e402f Mon Sep 17 00:00:00 2001 From: Vladyslav Tsybuliak Date: Sat, 28 Sep 2024 20:16:22 +0300 Subject: [PATCH 52/52] Add migrations --- task/migrations/0007_alter_tag_name.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 task/migrations/0007_alter_tag_name.py diff --git a/task/migrations/0007_alter_tag_name.py b/task/migrations/0007_alter_tag_name.py new file mode 100644 index 0000000..26db425 --- /dev/null +++ b/task/migrations/0007_alter_tag_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.1 on 2024-09-28 17:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("task", "0006_alter_task_is_completed"), + ] + + operations = [ + migrations.AlterField( + model_name="tag", + name="name", + field=models.CharField(max_length=63, unique=True), + ), + ]