diff --git a/README.md b/README.md new file mode 100644 index 00000000..0594ef9b --- /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/) diff --git a/djangocrud/settings.py b/djangocrud/settings.py index 3bffbba4..38dfee71 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 fe947ad6..2125df61 100644 --- a/djangocrud/urls.py +++ b/djangocrud/urls.py @@ -23,10 +23,11 @@ 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'), 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'), ] diff --git a/tasks/forms.py b/tasks/forms.py index 4f39411b..b633d3d3 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'] \ 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 ea0cbfe5..cd73c614 100644 --- a/tasks/models.py +++ b/tasks/models.py @@ -10,6 +10,8 @@ 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) + 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 95ddbedd..1c9bb151 100644 --- a/tasks/templates/create_task.html +++ b/tasks/templates/create_task.html @@ -2,13 +2,21 @@ {% block content %} -

CReate task

+

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/templates/task_detail.html b/tasks/templates/task_detail.html index 1debd8fe..b8e9f476 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 8fa07fcf..30e88add 100644 --- a/tasks/templates/tasks.html +++ b/tasks/templates/tasks.html @@ -2,6 +2,16 @@

tasks

+
+ + + +
+
    {% for task in tasks %}
  • diff --git a/tasks/tests.py b/tasks/tests.py index 7ce503c2..eb3bff43 100644 --- a/tasks/tests.py +++ b/tasks/tests.py @@ -1,3 +1,52 @@ 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): + username_template = 'EGRM23' + password_template = 'V6E388KR' + title_template = 'Tarea Compartida' + 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 + ) + + 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()) + + 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 diff --git a/tasks/views.py b/tasks/views.py index 4a3e2045..1458be34 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -6,15 +6,12 @@ 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.html', {"form": UserCreationForm}) + return render(request, signup_template, {"form": UserCreationForm}) else: if request.POST["password1"] == request.POST["password2"]: @@ -25,15 +22,25 @@ 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 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): @@ -51,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."}) @@ -82,8 +91,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 +108,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')