Skip to content

Commit da60567

Browse files
committed
labels added
1 parent 39caf3f commit da60567

File tree

13 files changed

+167
-11
lines changed

13 files changed

+167
-11
lines changed

task_manager/labels/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33

44
class LabelsConfig(AppConfig):
55
default_auto_field = 'django.db.models.BigAutoField'
6-
name = 'labels'
6+
name = 'task_manager.labels'

task_manager/labels/forms.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django import forms
2+
from .models import Label
3+
4+
class LabelForm(forms.ModelForm):
5+
class Meta:
6+
model = Label
7+
fields = ("name",)

task_manager/labels/models.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
11
from django.db import models
2+
from django.utils.translation import gettext_lazy as _
23

3-
# Create your models here.
4+
5+
class Label(models.Model):
6+
name = models.CharField(_("Имя"), max_length=100, unique=True)
7+
created_at = models.DateTimeField(_("Дата создания"), auto_now_add=True)
8+
9+
class Meta:
10+
ordering = ("id",)
11+
verbose_name = _("Label")
12+
verbose_name_plural = _("Labels")
13+
14+
def __str__(self):
15+
return self.name

task_manager/labels/urls.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.urls import path
2+
from .views import (
3+
LabelListView, LabelCreateView, LabelUpdateView, LabelDeleteView,
4+
)
5+
6+
app_name = "labels"
7+
8+
urlpatterns = [
9+
path("", LabelListView.as_view(), name="index"),
10+
path("create/", LabelCreateView.as_view(), name="create"),
11+
path("<int:pk>/update/", LabelUpdateView.as_view(), name="update"),
12+
path("<int:pk>/delete/", LabelDeleteView.as_view(), name="delete"),
13+
]

task_manager/labels/views.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,57 @@
1-
from django.shortcuts import render
1+
from django.contrib import messages
2+
from django.contrib.auth.mixins import LoginRequiredMixin
3+
from django.urls import reverse_lazy
4+
from django.utils.translation import gettext_lazy as _
5+
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
26

3-
# Create your views here.
7+
from .forms import LabelForm
8+
from .models import Label
9+
10+
11+
class LabelListView(LoginRequiredMixin, ListView):
12+
model = Label
13+
template_name = "labels/index.html"
14+
context_object_name = "labels"
15+
16+
17+
class LabelCreateView(LoginRequiredMixin, CreateView):
18+
model = Label
19+
form_class = LabelForm
20+
template_name = "labels/form.html"
21+
success_url = reverse_lazy("labels:index")
22+
23+
def form_valid(self, form):
24+
messages.success(self.request, _("Метка успешно создана"))
25+
return super().form_valid(form)
26+
27+
28+
class LabelUpdateView(LoginRequiredMixin, UpdateView):
29+
model = Label
30+
form_class = LabelForm
31+
template_name = "labels/form.html"
32+
success_url = reverse_lazy("labels:index")
33+
34+
def form_valid(self, form):
35+
messages.success(self.request, _("Метка успешно обновлена"))
36+
return super().form_valid(form)
37+
38+
39+
class LabelDeleteView(LoginRequiredMixin, DeleteView):
40+
model = Label
41+
template_name = "labels/confirm_delete.html"
42+
success_url = reverse_lazy("labels:index")
43+
44+
def dispatch(self, request, *args, **kwargs):
45+
label = self.get_object()
46+
if label.labeled_tasks.exists():
47+
messages.error(request, _("Нельзя удалить метку, так как она связана с задачей"))
48+
return self.get_redirect_url()
49+
return super().dispatch(request, *args, **kwargs)
50+
51+
def get_redirect_url(self):
52+
from django.shortcuts import redirect
53+
return redirect("labels:index")
54+
55+
def delete(self, request, *args, **kwargs):
56+
messages.success(request, _("Метка успешно удалена"))
57+
return super().delete(request, *args, **kwargs)

task_manager/tasks/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from django.db import models
22
from django.contrib.auth.models import User
3+
4+
from task_manager.labels.models import Label
35
from task_manager.statuses.models import Status
46

57

@@ -10,6 +12,7 @@ class Task(models.Model):
1012
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name="created_tasks")
1113
executor = models.ForeignKey(User, on_delete=models.PROTECT, null=True, blank=True, related_name="executed_tasks")
1214
created_at = models.DateTimeField(auto_now_add=True)
15+
labels = models.ManyToManyField(Label, related_name="labeled_tasks", blank=True)
1316

1417
class Meta:
1518
ordering = ["id"]

task_manager/templates/base.html

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
{% endif %}
2727
<li class="nav-item"><a class="nav-link" href="{% url 'users:list' %}">Пользователи</a></li>
2828
{% if user.is_authenticated %}
29-
<li class="nav-item">
30-
<a class="nav-link" href="{% url 'statuses_index' %}">Статусы</a>
29+
<li class="nav-item">
30+
<a class="nav-link" href="{% url 'statuses_index' %}">Статусы</a>
31+
</li>
32+
<li class="nav-item">
33+
<a class="nav-link" href="{% url 'tasks_index' %}">Задачи</a>
34+
</li>
35+
<li class="nav-item">
36+
<a class="nav-link" href="{% url 'labels:index' %}">Метки</a>
3137
</li>
32-
<li class="nav-item">
33-
<a class="nav-link" href="{% url 'tasks_index' %}">Задачи</a>
34-
</li>
3538
{% endif %}
3639
</ul>
3740
</div>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{% extends "base.html" %}
2+
3+
{% block content %}
4+
<h1 class="mb-3">Удалить метку</h1>
5+
6+
<p>Вы уверены, что хотите удалить метку <strong>{{ object.name }}</strong>?</p>
7+
8+
<form method="post">
9+
{% csrf_token %}
10+
<button type="submit" class="btn btn-danger">Да, удалить</button>
11+
<a href="{% url 'labels:index' %}" class="btn btn-secondary">Отмена</a>
12+
</form>
13+
{% endblock %}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{% extends "base.html" %}
2+
3+
{% block content %}
4+
<h1 class="mb-3">
5+
{% if object %}
6+
Изменить метку
7+
{% else %}
8+
Создать метку
9+
{% endif %}
10+
</h1>
11+
12+
<form method="post">
13+
{% csrf_token %}
14+
{{ form.as_p }}
15+
<button type="submit" class="btn btn-primary">Сохранить</button>
16+
<a href="{% url 'labels:index' %}" class="btn btn-secondary">Отмена</a>
17+
</form>
18+
{% endblock %}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<h1>Метки</h1>
4+
5+
<p><a class="btn btn-primary" href="{% url 'labels:create' %}">Создать метку</a></p>
6+
7+
<table class="table table-striped align-middle">
8+
<thead>
9+
<tr>
10+
<th>ID</th>
11+
<th>Имя</th>
12+
<th>Дата создания</th>
13+
<th></th>
14+
</tr>
15+
</thead>
16+
<tbody>
17+
{% for label in labels %}
18+
<tr>
19+
<td>{{ label.id }}</td>
20+
<td>{{ label.name }}</td>
21+
<td>{{ label.created_at|date:"d.m.Y H:i" }}</td>
22+
<td class="text-end">
23+
<a class="btn btn-sm btn-outline-secondary" href="{% url 'labels:update' label.pk %}">Изменить</a>
24+
<a class="btn btn-sm btn-outline-danger" href="{% url 'labels:delete' label.pk %}">Удалить</a>
25+
</td>
26+
</tr>
27+
{% empty %}
28+
<tr><td colspan="4">Пока нет меток.</td></tr>
29+
{% endfor %}
30+
</tbody>
31+
</table>
32+
{% endblock %}

0 commit comments

Comments
 (0)