From 53ef725b26ff509c5b93da7582d6a9751e952cb5 Mon Sep 17 00:00:00 2001 From: "3xsmq._" <103955471+SergioMenaQuispe@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:17:07 -0500 Subject: [PATCH 01/10] Create README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..0594ef9 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Pasos para iniciar proyecto + +Primero tener descargado sqlite e iniciar el ejecutable de sqlite3. +[Link de descarga del .zip](https://www.sqlite.org/2023/sqlite-tools-win-x64-3440200.zip) + + +1. `pip install -r requirements.txt` +2. `python manage.py makemigrations` +3. `python manage.py migrate` +4. `python manage.py createsuperuser` +5. `python manage.py runserver` +6. Ingresar a tu navegador en el puerto 8000 [http://127.0.0.1:8000/](http://127.0.0.1:8000/) From 7ffed4d099b2ee6cb38b0d1d1275f537ab459bd3 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:04:23 -0500 Subject: [PATCH 02/10] Arregla bugs de redireccionamiento --- djangocrud/settings.py | 2 +- djangocrud/urls.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/djangocrud/settings.py b/djangocrud/settings.py index 3bffbba..38dfee7 100644 --- a/djangocrud/settings.py +++ b/djangocrud/settings.py @@ -116,7 +116,7 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ -STATIC_URL = 'static/' +STATIC_URL = '/static/' LOGIN_URL = '/signin' diff --git a/djangocrud/urls.py b/djangocrud/urls.py index fe947ad..45f8355 100644 --- a/djangocrud/urls.py +++ b/djangocrud/urls.py @@ -27,6 +27,6 @@ path('signin/', views.signin, name='signin'), path('create_task/', views.create_task, name='create_task'), path('tasks/', views.task_detail, name='task_detail'), - path('taks//complete', views.complete_task, name='complete_task'), + path('tasks//complete', views.complete_task, name='complete_task'), path('tasks//delete', views.delete_task, name='delete_task'), ] From 0cb15c39412e08037be5ad0f24ef39bb5d8d2156 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:13:56 -0500 Subject: [PATCH 03/10] =?UTF-8?q?Implementa=20la=20funci=C3=B3n=20de=20tar?= =?UTF-8?q?eas=20compartidas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- djangocrud/urls.py | 1 + tasks/forms.py | 2 +- tasks/models.py | 1 + tasks/templates/create_task.html | 2 +- tasks/templates/task_detail.html | 14 +++++++++----- tasks/templates/tasks.html | 10 ++++++++++ tasks/views.py | 16 ++++++++++++++-- 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/djangocrud/urls.py b/djangocrud/urls.py index 45f8355..2125df6 100644 --- a/djangocrud/urls.py +++ b/djangocrud/urls.py @@ -23,6 +23,7 @@ path('signup/', views.signup, name='signup'), path('tasks/', views.tasks, name='tasks'), path('tasks_completed/', views.tasks_completed, name='tasks_completed'), + path('shared_tasks/', views.shared_tasks, name='shared_tasks'), path('logout/', views.signout, name='logout'), path('signin/', views.signin, name='signin'), path('create_task/', views.create_task, name='create_task'), diff --git a/tasks/forms.py b/tasks/forms.py index 4f39411..ffee3c9 100644 --- a/tasks/forms.py +++ b/tasks/forms.py @@ -4,4 +4,4 @@ class TaskForm(ModelForm): class Meta: model = Task - fields = ['title', 'description', 'important'] \ No newline at end of file + fields = ['title', 'description', 'important', 'shared'] \ No newline at end of file diff --git a/tasks/models.py b/tasks/models.py index ea0cbfe..8b60efb 100644 --- a/tasks/models.py +++ b/tasks/models.py @@ -10,6 +10,7 @@ class Task(models.Model): datecompleted = models.DateTimeField(null=True, blank=True) important = models.BooleanField(default=False) user = models.ForeignKey(User, on_delete=models.CASCADE) + shared = models.BooleanField(default=False) def __str__(self): return self.title + ' - ' + self.user.username diff --git a/tasks/templates/create_task.html b/tasks/templates/create_task.html index 95ddbed..7c0c610 100644 --- a/tasks/templates/create_task.html +++ b/tasks/templates/create_task.html @@ -2,7 +2,7 @@ {% block content %} -

CReate task

+

Create task

{{error}}
diff --git a/tasks/templates/task_detail.html b/tasks/templates/task_detail.html index 1debd8f..b8e9f47 100644 --- a/tasks/templates/task_detail.html +++ b/tasks/templates/task_detail.html @@ -4,28 +4,32 @@ {{task.title}} +{% if_is_shared_task %} +

This is a shared task

+{% endif %} + {{error}} {% csrf_token %} {{form.as_p}} -
{% csrf_token %} -
{% csrf_token %} -
diff --git a/tasks/templates/tasks.html b/tasks/templates/tasks.html index 8fa07fc..30e88ad 100644 --- a/tasks/templates/tasks.html +++ b/tasks/templates/tasks.html @@ -2,6 +2,16 @@

tasks

+
+ + + +
+
    {% for task in tasks %}
  • diff --git a/tasks/views.py b/tasks/views.py index 4a3e204..9866707 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -33,7 +33,17 @@ def signup(request): @login_required def tasks(request): tasks = Task.objects.filter(user=request.user, datecompleted__isnull=True) - return render(request, 'tasks.html', {"tasks": tasks}) + filter_type = request.GET.get('filter','all') + if filter_type == 'shared': + tasks = tasks.filter(shared=True) + elif filter_type == 'normal': + tasks = tasks.filter(shared=False) + return render(request, 'tasks.html', {"tasks": tasks, "filter_type": filter_type}) + +@login_required +def shared_tasks(request): + shared_tasks = Task.objects.filter(shared=True) + return render(request, 'shared_tasks.html', {"tasks": shared_tasks}) @login_required def tasks_completed(request): @@ -82,8 +92,9 @@ def signin(request): def task_detail(request, task_id): if request.method == 'GET': task = get_object_or_404(Task, pk=task_id, user=request.user) + is_shared_task = task.shared form = TaskForm(instance=task) - return render(request, 'task_detail.html', {'task': task, 'form': form}) + return render(request, 'task_detail.html', {'task': task, 'form': form, 'is_shared_task': is_shared_task}) else: try: task = get_object_or_404(Task, pk=task_id, user=request.user) @@ -98,6 +109,7 @@ def complete_task(request, task_id): task = get_object_or_404(Task, pk=task_id, user=request.user) if request.method == 'POST': task.datecompleted = timezone.now() + task.shared = request.POST.get('shared', False) task.save() return redirect('tasks') From be96499b4a1ddfd1e30c32ed918b700e03c65d9b Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:16:06 -0500 Subject: [PATCH 04/10] =?UTF-8?q?Arregla=20vulnerabilidad=20de=20duplicaci?= =?UTF-8?q?=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tasks/views.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tasks/views.py b/tasks/views.py index 9866707..0515668 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -13,8 +13,10 @@ def signup(request): + + signup_template = 'signup.html' if request.method == 'GET': - return render(request, 'signup.html', {"form": UserCreationForm}) + return render(request, signup_template, {"form": UserCreationForm}) else: if request.POST["password1"] == request.POST["password2"]: @@ -25,9 +27,9 @@ def signup(request): login(request, user) return redirect('tasks') except IntegrityError: - return render(request, 'signup.html', {"form": UserCreationForm, "error": "Username already exists."}) + return render(request, signup_template, {"form": UserCreationForm, "error": "Username already exists."}) - return render(request, 'signup.html', {"form": UserCreationForm, "error": "Passwords did not match."}) + return render(request, signup_template, {"form": UserCreationForm, "error": "Passwords did not match."}) @login_required From 4ae3f81da35177a8dbd039ea61f9834418fdc421 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:17:52 -0500 Subject: [PATCH 05/10] Agrega casos de prueba respecto a la funcionalidad de tareas compartidas --- tasks/tests.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tasks/tests.py b/tasks/tests.py index 7ce503c..81f4454 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -1,3 +1,25 @@ from django.test import TestCase +from django.contrib.auth.models import User +from django.urls import reverse +from .models import Task -# Create your tests here. +class SharedTasksTestCase(TestCase): + def setUp(self): + self.client.login(username='EGRM23', password='V6E388KR') + + def test_create_shared_task(self): + response = self.client.post(reverse('create_task'), { + 'title': 'Tarea Compartida', + 'description': 'Esta es una tarea compartida', + 'shared': True, + }) + + self.assertEqual(response.status_code, 302) + self.assertTrue(Task.objects.filter(title='Tarea Compartida', shared=True).exists()) + + def test_view_shared_tasks(self): + response = self.client.get(reverse('shared_tasks')) + + # Verificar que la página se carga correctamente y contiene las tareas compartidas + self.assertEqual(response.status_code, 200) # 200 es el código de éxito + self.assertContains(response, 'Tarea Compartida') \ No newline at end of file From 1d41a438ab5904ab1c99ab0f15e717ab48d10f9a Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:19:59 -0500 Subject: [PATCH 06/10] =?UTF-8?q?Arregla=20malas=20pr=C3=A1cticas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tasks/tests.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tasks/tests.py b/tasks/tests.py index 81f4454..743b1e1 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -4,22 +4,27 @@ from .models import Task class SharedTasksTestCase(TestCase): + username_template = 'EGRM23' + password_template = 'V6E388KR' + title_template = 'Tarea Compartida' + description_template = 'Esta es una tarea compartida' + def setUp(self): - self.client.login(username='EGRM23', password='V6E388KR') + self.client.login(username=self.username_template, password=self.password_template) def test_create_shared_task(self): response = self.client.post(reverse('create_task'), { - 'title': 'Tarea Compartida', - 'description': 'Esta es una tarea compartida', + 'title': self.username_template, + 'description': self.description_template, 'shared': True, }) self.assertEqual(response.status_code, 302) - self.assertTrue(Task.objects.filter(title='Tarea Compartida', shared=True).exists()) + self.assertTrue(Task.objects.filter(title=self.username_template, shared=True).exists()) def test_view_shared_tasks(self): response = self.client.get(reverse('shared_tasks')) # Verificar que la página se carga correctamente y contiene las tareas compartidas self.assertEqual(response.status_code, 200) # 200 es el código de éxito - self.assertContains(response, 'Tarea Compartida') \ No newline at end of file + self.assertContains(response, self.username_template) \ No newline at end of file From 86af988c4b03dae9a2ce4029d363531737cbc4a0 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:21:30 -0500 Subject: [PATCH 07/10] Elimina espacios innnecesarios --- tasks/tests.py | 3 +-- tasks/views.py | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/tasks/tests.py b/tasks/tests.py index 743b1e1..cb0a3d0 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -25,6 +25,5 @@ def test_create_shared_task(self): def test_view_shared_tasks(self): response = self.client.get(reverse('shared_tasks')) - # Verificar que la página se carga correctamente y contiene las tareas compartidas - self.assertEqual(response.status_code, 200) # 200 es el código de éxito + self.assertEqual(response.status_code, 200) self.assertContains(response, self.username_template) \ No newline at end of file diff --git a/tasks/views.py b/tasks/views.py index 0515668..241c1c2 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -6,14 +6,9 @@ from django.utils import timezone from django.contrib.auth.decorators import login_required from .models import Task - from .forms import TaskForm -# Create your views here. - - def signup(request): - signup_template = 'signup.html' if request.method == 'GET': return render(request, signup_template, {"form": UserCreationForm}) From cd506a55c0ef781f960960a433e308b71c09ac86 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:26:20 -0500 Subject: [PATCH 08/10] Arregla caso de prueba en caso de cuenta inexistente --- tasks/tests.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tasks/tests.py b/tasks/tests.py index cb0a3d0..a0b4976 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -10,6 +10,12 @@ class SharedTasksTestCase(TestCase): description_template = 'Esta es una tarea compartida' def setUp(self): + user_exists = User.objects.filter(username=self.username_template).exists() + if not user_exists: + User.objects.create_user( + username=self.username_template, + password=self.password_template + ) self.client.login(username=self.username_template, password=self.password_template) def test_create_shared_task(self): @@ -18,12 +24,10 @@ def test_create_shared_task(self): 'description': self.description_template, 'shared': True, }) - self.assertEqual(response.status_code, 302) self.assertTrue(Task.objects.filter(title=self.username_template, shared=True).exists()) def test_view_shared_tasks(self): response = self.client.get(reverse('shared_tasks')) - self.assertEqual(response.status_code, 200) self.assertContains(response, self.username_template) \ No newline at end of file From aeef34be4bcfbfe6595b7f11a2fb363c94891982 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:43:17 -0500 Subject: [PATCH 09/10] Arregla funcionalidad de tareas compartidas, solo unos usuarios --- tasks/forms.py | 11 +++++++++-- tasks/models.py | 1 + tasks/templates/create_task.html | 12 ++++++++++-- tasks/views.py | 2 ++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tasks/forms.py b/tasks/forms.py index ffee3c9..b633d3d 100644 --- a/tasks/forms.py +++ b/tasks/forms.py @@ -1,7 +1,14 @@ -from django.forms import ModelForm +from django import forms +from django.contrib.auth.models import User from .models import Task -class TaskForm(ModelForm): +class TaskForm(forms.ModelForm): + shared_with = forms.ModelMultipleChoiceField( + queryset=User.objects.all(), + widget=forms.CheckboxSelectMultiple, + required=False, + ) + class Meta: model = Task fields = ['title', 'description', 'important', 'shared'] \ No newline at end of file diff --git a/tasks/models.py b/tasks/models.py index 8b60efb..cd73c61 100644 --- a/tasks/models.py +++ b/tasks/models.py @@ -11,6 +11,7 @@ class Task(models.Model): important = models.BooleanField(default=False) user = models.ForeignKey(User, on_delete=models.CASCADE) shared = models.BooleanField(default=False) + shared_with = models.ManyToManyField(User, related_name='shared_tasks', blank=True) def __str__(self): return self.title + ' - ' + self.user.username diff --git a/tasks/templates/create_task.html b/tasks/templates/create_task.html index 7c0c610..1c9bb15 100644 --- a/tasks/templates/create_task.html +++ b/tasks/templates/create_task.html @@ -7,8 +7,16 @@

    Create task

    {{error}}
    {% csrf_token %} - {{form}} - + {{form.title.label_tag}} {{form.title}} +
    + {{form.description.label_tag}} {{form.description}} +
    + {{form.important}} {{form.important.label_tag}} +
    + {{form.shared}} {{form.shared.label_tag}} +
    + {{ form.shared_with.label_tag }} {{ form.shared_with }} +
    {% endblock %} \ No newline at end of file diff --git a/tasks/views.py b/tasks/views.py index 241c1c2..1458be3 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -58,6 +58,8 @@ def create_task(request): new_task = form.save(commit=False) new_task.user = request.user new_task.save() + shared_with_users = request.POST.getlist('shared_with') + new_task.shared_with.set(shared_with_users) return redirect('tasks') except ValueError: return render(request, 'create_task.html', {"form": TaskForm, "error": "Error creating task."}) From a1377310204d17fac2b7c11bded8b639ac798520 Mon Sep 17 00:00:00 2001 From: Eduardo Ruiz Date: Tue, 26 Dec 2023 19:54:10 -0500 Subject: [PATCH 10/10] Ajusta los casos de prueba a los cmabios hechos --- tasks/tests.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/tasks/tests.py b/tasks/tests.py index a0b4976..eb3bff4 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -15,14 +15,33 @@ def setUp(self): User.objects.create_user( username=self.username_template, password=self.password_template - ) + ) + + users_data = [ + {'username': 'UsuarioPrueba1', 'password': 'contra1molde'}, + {'username': 'UsuarioPrueba2', 'password': 'contra2molde'}, + {'username': 'UsuarioPrueba3', 'password': 'contra3molde'}, + ] + + for user_data in users_data: + user_exists = User.objects.filter(username=user_data['username']).exists() + if not user_exists: + User.objects.create_user( + username=user_data['username'], + password=user_data['password'] + ) + self.client.login(username=self.username_template, password=self.password_template) def test_create_shared_task(self): + user1_id = User.objects.get(username='UsuarioPrueba1').id + user2_id = User.objects.get(username='UsuarioPrueba2').id + response = self.client.post(reverse('create_task'), { 'title': self.username_template, 'description': self.description_template, 'shared': True, + 'shared_with': [user1_id, user2_id] }) self.assertEqual(response.status_code, 302) self.assertTrue(Task.objects.filter(title=self.username_template, shared=True).exists())