Skip to content

Commit 59cf424

Browse files
committed
statuses added
1 parent 97851de commit 59cf424

File tree

12 files changed

+259
-0
lines changed

12 files changed

+259
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# tests/test_statuses_simple.py
2+
import pytest
3+
from django.contrib.auth.models import User
4+
from django.test import Client
5+
6+
from statuses.models import Status
7+
8+
9+
@pytest.fixture
10+
def user(db):
11+
return User.objects.create_user(username="u", password="p12345678")
12+
13+
14+
@pytest.fixture
15+
def auth_client(user):
16+
c = Client()
17+
c.login(username="u", password="p12345678")
18+
return c
19+
20+
21+
@pytest.mark.django_db
22+
def test_login_required(client):
23+
# Любая страница из раздела должна уводить на логин
24+
r1 = client.get("/statuses/")
25+
r2 = client.get("/statuses/create/")
26+
assert r1.status_code in (302, 301)
27+
assert r2.status_code in (302, 301)
28+
assert "login" in r1.url
29+
assert "login" in r2.url
30+
31+
32+
@pytest.mark.django_db
33+
def test_list(auth_client):
34+
Status.objects.create(name="новый")
35+
Status.objects.create(name="в работе")
36+
resp = auth_client.get("/statuses/")
37+
assert resp.status_code == 200
38+
html = resp.content.decode()
39+
assert "новый" in html
40+
assert "в работе" in html
41+
42+
43+
@pytest.mark.django_db
44+
def test_create(auth_client):
45+
resp = auth_client.post("/statuses/create/", data={"name": "на тестировании"})
46+
assert resp.status_code in (302, 301)
47+
assert Status.objects.filter(name="на тестировании").exists()
48+
49+
50+
@pytest.mark.django_db
51+
def test_update(auth_client):
52+
st = Status.objects.create(name="черновик")
53+
resp = auth_client.post(f"/statuses/{st.pk}/update/", data={"name": "завершён"})
54+
assert resp.status_code in (302, 301)
55+
st.refresh_from_db()
56+
assert st.name == "завершён"
57+
58+
59+
@pytest.mark.django_db
60+
def test_delete(auth_client):
61+
st = Status.objects.create(name="временный")
62+
# Страница подтверждения удаления открывается
63+
get_resp = auth_client.get(f"/statuses/{st.pk}/delete/")
64+
assert get_resp.status_code == 200
65+
# Удаление проходит
66+
post_resp = auth_client.post(f"/statuses/{st.pk}/delete/")
67+
assert post_resp.status_code in (302, 301)
68+
assert not Status.objects.filter(pk=st.pk).exists()

db.sqlite3

8 KB
Binary file not shown.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dependencies = [
1111
"gunicorn",
1212
"whitenoise",
1313
"django-bootstrap5>=25.2",
14+
"pytest>=8.4.2",
1415
]
1516

1617
[dependency-groups]

statuses/forms.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django import forms
2+
from .models import Status
3+
4+
5+
class StatusForm(forms.ModelForm):
6+
class Meta:
7+
model = Status
8+
fields = ["name"]
9+
widgets = {
10+
"name": forms.TextInput(attrs={"class": "form-control"}),
11+
}

statuses/urls.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.urls import path
2+
from .views import (
3+
StatusListView, StatusCreateView, StatusUpdateView, StatusDeleteView
4+
)
5+
6+
urlpatterns = [
7+
path("", StatusListView.as_view(), name="statuses_index"),
8+
path("create/", StatusCreateView.as_view(), name="statuses_create"),
9+
path("<int:pk>/update/", StatusUpdateView.as_view(), name="statuses_update"),
10+
path("<int:pk>/delete/", StatusDeleteView.as_view(), name="statuses_delete"),
11+
]

task_manager/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
'django_bootstrap5',
4545
'accounts',
4646
'tasks',
47+
'statuses',
4748
]
4849

4950
MIDDLEWARE = [

task_manager/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@
2222
path('admin/', admin.site.urls),
2323
path("", views.index, name="home"),
2424
path("users/", include("accounts.urls", namespace="users")),
25+
path("statuses/", include("statuses.urls")),
2526
]

templates/base.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<li class="nav-item"><a class="nav-link" href="{% url 'users:create' %}">Регистрация</a></li>
2626
{% endif %}
2727
<li class="nav-item"><a class="nav-link" href="{% url 'users:list' %}">Пользователи</a></li>
28+
<li class="nav-item"><a class="nav-link" href="{% url 'statuses_index' %}">Статусы</a></li>
2829
</ul>
2930
</div>
3031
</div>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<h1>Удалить статус</h1>
4+
<p>Точно удалить статус «{{ object }}»?</p>
5+
<form method="post">
6+
{% csrf_token %}
7+
<button type="submit" class="btn btn-danger">Удалить</button>
8+
<a href="{% url 'statuses_index' %}" class="btn btn-link">Отмена</a>
9+
</form>
10+
{% endblock %}

templates/statuses/form.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
<h1>{{ object|default_if_none:"Создать статус" }}</h1>
4+
5+
<form method="post">
6+
{% csrf_token %}
7+
{{ form.non_field_errors }}
8+
<div class="mb-3">
9+
<label for="{{ form.name.id_for_label }}" class="form-label">Название</label>
10+
{{ form.name }}
11+
{% if form.name.errors %}
12+
<div class="text-danger">{{ form.name.errors|striptags }}</div>
13+
{% endif %}
14+
</div>
15+
<button type="submit" class="btn btn-primary">Сохранить</button>
16+
<a href="{% url 'statuses_index' %}" class="btn btn-link">Отмена</a>
17+
</form>
18+
{% endblock %}

0 commit comments

Comments
 (0)