punkweb-bb 0.1.3__py3-none-any.whl → 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- punkweb_bb/__pycache__/forms.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/guests.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/middleware.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/models.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/settings.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/tests.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/urls.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/utils.cpython-311.pyc +0 -0
- punkweb_bb/__pycache__/views.cpython-311.pyc +0 -0
- punkweb_bb/forms.py +40 -7
- punkweb_bb/guests.py +20 -0
- punkweb_bb/middleware.py +7 -0
- punkweb_bb/models.py +21 -0
- punkweb_bb/settings.py +3 -0
- punkweb_bb/static/punkweb_bb/css/category-form.css +24 -0
- punkweb_bb/static/punkweb_bb/css/index.css +6 -0
- punkweb_bb/static/punkweb_bb/css/punkweb.css +84 -5
- punkweb_bb/static/punkweb_bb/css/shoutbox.css +13 -2
- punkweb_bb/static/punkweb_bb/css/subcategory-form.css +24 -0
- punkweb_bb/static/punkweb_bb/css/subcategory.css +12 -0
- punkweb_bb/static/punkweb_bb/css/thread.css +19 -0
- punkweb_bb/static/punkweb_bb/css/variables.css +1 -0
- punkweb_bb/templates/punkweb_bb/category_create.html +50 -0
- punkweb_bb/templates/punkweb_bb/category_update.html +53 -0
- punkweb_bb/templates/punkweb_bb/index.html +46 -7
- punkweb_bb/templates/punkweb_bb/partials/category_delete.html +11 -0
- punkweb_bb/templates/punkweb_bb/partials/shout_delete.html +11 -0
- punkweb_bb/templates/punkweb_bb/partials/subcategory_delete.html +11 -0
- punkweb_bb/templates/punkweb_bb/shoutbox/shout_list.html +14 -4
- punkweb_bb/templates/punkweb_bb/subcategory.html +21 -6
- punkweb_bb/templates/punkweb_bb/subcategory_create.html +53 -0
- punkweb_bb/templates/punkweb_bb/subcategory_update.html +56 -0
- punkweb_bb/templates/punkweb_bb/thread.html +26 -6
- punkweb_bb/templates/punkweb_bb/thread_create.html +1 -0
- punkweb_bb/templatetags/__pycache__/can_delete.cpython-311.pyc +0 -0
- punkweb_bb/templatetags/__pycache__/can_edit.cpython-311.pyc +0 -0
- punkweb_bb/templatetags/__pycache__/can_post.cpython-311.pyc +0 -0
- punkweb_bb/templatetags/can_delete.py +8 -0
- punkweb_bb/templatetags/can_edit.py +8 -0
- punkweb_bb/templatetags/can_post.py +8 -0
- punkweb_bb/tests.py +19 -8
- punkweb_bb/urls.py +27 -0
- punkweb_bb/utils.py +17 -0
- punkweb_bb/views.py +232 -38
- {punkweb_bb-0.1.3.dist-info → punkweb_bb-0.2.0.dist-info}/METADATA +6 -2
- {punkweb_bb-0.1.3.dist-info → punkweb_bb-0.2.0.dist-info}/RECORD +49 -30
- {punkweb_bb-0.1.3.dist-info → punkweb_bb-0.2.0.dist-info}/LICENSE +0 -0
- {punkweb_bb-0.1.3.dist-info → punkweb_bb-0.2.0.dist-info}/WHEEL +0 -0
- {punkweb_bb-0.1.3.dist-info → punkweb_bb-0.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
{% load shoutbox_bbcode %}
|
|
1
|
+
{% load shoutbox_bbcode can_delete %}
|
|
2
2
|
|
|
3
3
|
{% for shout in shouts %}
|
|
4
4
|
<div class="shoutbox__shout">
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
<div class="shoutbox__shout__content">
|
|
6
|
+
<span>{{shout.created_at|date:'g:i A'}}</span>
|
|
7
|
+
<span><a href="{% url 'punkweb_bb:profile' shout.user.id %}">{{shout.user.username}}</a>: </span>
|
|
8
|
+
<span>{{ shout.content | safe | shoutbox_bbcode }}</span>
|
|
9
|
+
</div>
|
|
10
|
+
{% if shout|can_delete:request.user %}
|
|
11
|
+
<div class="shoutbox__shout__actions">
|
|
12
|
+
<button class="pw-icon-button danger xs" hx-get="{% url 'punkweb_bb:shout_delete' shout.id %}"
|
|
13
|
+
hx-target="#modal-portal">
|
|
14
|
+
<span class="material-symbols-outlined">close</span>
|
|
15
|
+
</button>
|
|
16
|
+
</div>
|
|
17
|
+
{% endif %}
|
|
8
18
|
</div>
|
|
9
19
|
{% endfor %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% extends 'punkweb_bb/base.html' %}
|
|
2
|
-
{% load static humanize_int %}
|
|
2
|
+
{% load static humanize_int can_post %}
|
|
3
3
|
|
|
4
4
|
{% block title_prefix %}{{subcategory.name}} | {% endblock%}
|
|
5
5
|
|
|
@@ -24,21 +24,36 @@
|
|
|
24
24
|
</nav>
|
|
25
25
|
|
|
26
26
|
<div class="subcategory__header">
|
|
27
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
<div class="subcategory__header__name">
|
|
28
|
+
<h1>{{subcategory.name}}</h1>
|
|
29
|
+
{% if perms.punkweb_bb.change_subcategory or perms.punkweb_bb.delete_subcategory %}
|
|
30
|
+
<div class="subcategory__header__actions">
|
|
31
|
+
{% if perms.punkweb_bb.change_subcategory %}
|
|
32
|
+
<a class="pw-button ghost xs" href="{% url 'punkweb_bb:subcategory_update' subcategory.slug %}">
|
|
33
|
+
Edit
|
|
34
|
+
</a>
|
|
35
|
+
{% endif %}
|
|
36
|
+
{% if perms.punkweb_bb.delete_subcategory %}
|
|
37
|
+
<a class="pw-button ghost danger xs" hx-get="{% url 'punkweb_bb:subcategory_delete' subcategory.slug %}" hx-target="#modal-portal">
|
|
38
|
+
Delete
|
|
39
|
+
</a>
|
|
40
|
+
{% endif %}
|
|
41
|
+
</div>
|
|
42
|
+
{% endif %}
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
{% if subcategory|can_post:request.user %}
|
|
30
46
|
<a class="pw-button ghost primary" href="{% url 'punkweb_bb:thread_create' subcategory.slug %}">Create Thread</a>
|
|
31
47
|
{% else %}
|
|
32
48
|
<button
|
|
33
49
|
class="pw-button ghost primary"
|
|
34
50
|
disabled
|
|
35
51
|
href="{% url 'punkweb_bb:thread_create' subcategory.slug %}"
|
|
36
|
-
title="
|
|
52
|
+
title="You do not have permission to create a thread in this subcategory."
|
|
37
53
|
>
|
|
38
54
|
Create Thread
|
|
39
55
|
</button>
|
|
40
56
|
{% endif %}
|
|
41
|
-
{% endif %}
|
|
42
57
|
</div>
|
|
43
58
|
|
|
44
59
|
<div class="pw-card fluid margin">
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{% extends 'punkweb_bb/base.html' %}
|
|
2
|
+
{% load static %}
|
|
3
|
+
|
|
4
|
+
{% block title_prefix %}Create Subcategory | {% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block extra_head %}
|
|
7
|
+
{{form.media.css}}
|
|
8
|
+
<link rel="stylesheet" href="{% static 'punkweb_bb/css/subcategory-form.css' %}" />
|
|
9
|
+
{% endblock %}
|
|
10
|
+
|
|
11
|
+
{% block content %}
|
|
12
|
+
|
|
13
|
+
<nav>
|
|
14
|
+
<ul class="pw-breadcrumb">
|
|
15
|
+
<li class="pw-breadcrumb-item">
|
|
16
|
+
<a href="{% url 'punkweb_bb:index' %}">Home</a>
|
|
17
|
+
</li>
|
|
18
|
+
<li class="pw-breadcrumb-item">
|
|
19
|
+
<a href="{{category.get_absolute_url}}">{{category.name}}</a>
|
|
20
|
+
</li>
|
|
21
|
+
<li class="pw-breadcrumb-item active">
|
|
22
|
+
Create Subcategory
|
|
23
|
+
</li>
|
|
24
|
+
</ul>
|
|
25
|
+
</nav>
|
|
26
|
+
|
|
27
|
+
<div class="pw-card fluid">
|
|
28
|
+
<div class="pw-card-header">Create Subcategory</div>
|
|
29
|
+
<div class="pw-card-content">
|
|
30
|
+
<form class="subcategoryForm" action="{% url 'punkweb_bb:subcategory_create' category.slug %}" method="post">
|
|
31
|
+
{% csrf_token %}
|
|
32
|
+
{% for field in form %}
|
|
33
|
+
<div class="subcategoryForm__field">
|
|
34
|
+
<label class="pw-input-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
|
|
35
|
+
{{ field }}
|
|
36
|
+
</div>
|
|
37
|
+
{% endfor %}
|
|
38
|
+
{% if form.non_field_errors %}
|
|
39
|
+
{{ form.non_field_errors }}
|
|
40
|
+
{% endif %}
|
|
41
|
+
<div class="subcategoryForm__actions">
|
|
42
|
+
<a class="pw-button default" href="{% url 'punkweb_bb:index' %}" type="submit">Cancel</a>
|
|
43
|
+
<button class="pw-button raised primary" type="submit">Create</button>
|
|
44
|
+
</div>
|
|
45
|
+
</form>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
{% endblock %}
|
|
50
|
+
|
|
51
|
+
{% block extra_script %}
|
|
52
|
+
{{form.media.js}}
|
|
53
|
+
{% endblock %}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{% extends 'punkweb_bb/base.html' %}
|
|
2
|
+
{% load static %}
|
|
3
|
+
|
|
4
|
+
{% block title_prefix %}Edit Subcategory | {% endblock %}
|
|
5
|
+
|
|
6
|
+
{% block extra_head %}
|
|
7
|
+
{{form.media.css}}
|
|
8
|
+
<link rel="stylesheet" href="{% static 'punkweb_bb/css/subcategory-form.css' %}" />
|
|
9
|
+
{% endblock %}
|
|
10
|
+
|
|
11
|
+
{% block content %}
|
|
12
|
+
|
|
13
|
+
<nav>
|
|
14
|
+
<ul class="pw-breadcrumb">
|
|
15
|
+
<li class="pw-breadcrumb-item">
|
|
16
|
+
<a href="{% url 'punkweb_bb:index' %}">Home</a>
|
|
17
|
+
</li>
|
|
18
|
+
<li class="pw-breadcrumb-item">
|
|
19
|
+
<a href="{{subcategory.category.get_absolute_url}}">{{subcategory.category.name}}</a>
|
|
20
|
+
</li>
|
|
21
|
+
<li class="pw-breadcrumb-item">
|
|
22
|
+
<a href="{{subcategory.get_absolute_url}}">{{subcategory.name}}</a>
|
|
23
|
+
</li>
|
|
24
|
+
<li class="pw-breadcrumb-item active">
|
|
25
|
+
Edit
|
|
26
|
+
</li>
|
|
27
|
+
</ul>
|
|
28
|
+
</nav>
|
|
29
|
+
|
|
30
|
+
<div class="pw-card fluid">
|
|
31
|
+
<div class="pw-card-header">Edit Subcategory</div>
|
|
32
|
+
<div class="pw-card-content">
|
|
33
|
+
<form class="subcategoryForm" action="{% url 'punkweb_bb:subcategory_update' subcategory.slug %}" method="post">
|
|
34
|
+
{% csrf_token %}
|
|
35
|
+
{% for field in form %}
|
|
36
|
+
<div class="subcategoryForm__field">
|
|
37
|
+
<label class="pw-input-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
|
|
38
|
+
{{ field }}
|
|
39
|
+
</div>
|
|
40
|
+
{% endfor %}
|
|
41
|
+
{% if form.non_field_errors %}
|
|
42
|
+
{{ form.non_field_errors }}
|
|
43
|
+
{% endif %}
|
|
44
|
+
<div class="subcategoryForm__actions">
|
|
45
|
+
<a class="pw-button default" href="{{subcategory.get_absolute_url}}">Cancel</a>
|
|
46
|
+
<button class="pw-button raised primary" type="submit">Save</button>
|
|
47
|
+
</div>
|
|
48
|
+
</form>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
{% endblock %}
|
|
53
|
+
|
|
54
|
+
{% block extra_script %}
|
|
55
|
+
{{form.media.js}}
|
|
56
|
+
{% endblock %}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{% extends 'punkweb_bb/base.html' %}
|
|
2
|
-
{% load static %}
|
|
2
|
+
{% load static can_delete can_edit can_post %}
|
|
3
3
|
|
|
4
4
|
{% block title_prefix %}{{thread.title}} | {% endblock %}
|
|
5
5
|
|
|
@@ -67,6 +67,13 @@
|
|
|
67
67
|
<div class="thread__user__info__value">{{thread.user.profile.post_count}}</div>
|
|
68
68
|
</div>
|
|
69
69
|
</div>
|
|
70
|
+
{% if thread.user.groups.all|length > 0 %}
|
|
71
|
+
<div class="thread__user__groups">
|
|
72
|
+
{% for group in thread.user.groups.all %}
|
|
73
|
+
<div class="thread__user__group">{{group.name}}</div>
|
|
74
|
+
{% endfor %}
|
|
75
|
+
</div>
|
|
76
|
+
{% endif %}
|
|
70
77
|
</div>
|
|
71
78
|
<div class="thread__main">
|
|
72
79
|
<div class="thread__content">
|
|
@@ -77,13 +84,17 @@
|
|
|
77
84
|
{{thread.user.profile.signature.rendered}}
|
|
78
85
|
</div>
|
|
79
86
|
{% endif %}
|
|
80
|
-
{% if thread.user
|
|
87
|
+
{% if thread|can_delete:request.user or thread|can_edit:request.user %}
|
|
81
88
|
<div class="thread__actions">
|
|
89
|
+
{% if thread|can_edit:request.user %}
|
|
82
90
|
<a class="pw-button ghost sm" href="{% url 'punkweb_bb:thread_update' thread.id %}">Edit</a>
|
|
91
|
+
{% endif %}
|
|
92
|
+
{% if thread|can_delete:request.user %}
|
|
83
93
|
<a class="pw-button ghost danger sm" hx-get="{% url 'punkweb_bb:thread_delete' thread.id %}"
|
|
84
94
|
hx-target="#modal-portal">
|
|
85
95
|
Delete
|
|
86
96
|
</a>
|
|
97
|
+
{% endif %}
|
|
87
98
|
</div>
|
|
88
99
|
{% endif %}
|
|
89
100
|
</div>
|
|
@@ -128,6 +139,13 @@
|
|
|
128
139
|
<div class="thread__user__info__value">{{post.user.profile.post_count}}</div>
|
|
129
140
|
</div>
|
|
130
141
|
</div>
|
|
142
|
+
{% if post.user.groups.all|length > 0 %}
|
|
143
|
+
<div class="thread__user__groups">
|
|
144
|
+
{% for group in post.user.groups.all %}
|
|
145
|
+
<div class="thread__user__group">{{group.name}}</div>
|
|
146
|
+
{% endfor %}
|
|
147
|
+
</div>
|
|
148
|
+
{% endif %}
|
|
131
149
|
</div>
|
|
132
150
|
<div class="thread__main">
|
|
133
151
|
<div class="thread__content">
|
|
@@ -138,13 +156,17 @@
|
|
|
138
156
|
{{post.user.profile.signature.rendered}}
|
|
139
157
|
</div>
|
|
140
158
|
{% endif %}
|
|
141
|
-
{% if post.user
|
|
159
|
+
{% if post|can_delete:request.user or post|can_edit:request.user %}
|
|
142
160
|
<div class="thread__actions">
|
|
161
|
+
{% if post|can_edit:request.user %}
|
|
143
162
|
<a class="pw-button ghost sm" hx-get="{% url 'punkweb_bb:post_update' post.id %}" hx-target="#modal-portal">Edit</a>
|
|
163
|
+
{% endif %}
|
|
164
|
+
{% if post|can_delete:request.user %}
|
|
144
165
|
<a class="pw-button ghost danger sm" hx-get="{% url 'punkweb_bb:post_delete' post.id %}"
|
|
145
166
|
hx-target="#modal-portal">
|
|
146
167
|
Delete
|
|
147
168
|
</a>
|
|
169
|
+
{% endif %}
|
|
148
170
|
</div>
|
|
149
171
|
{% endif %}
|
|
150
172
|
</div>
|
|
@@ -198,8 +220,7 @@
|
|
|
198
220
|
</nav>
|
|
199
221
|
{% endif %}
|
|
200
222
|
|
|
201
|
-
{% if request.user
|
|
202
|
-
{% if not thread.is_closed %}
|
|
223
|
+
{% if thread|can_post:request.user %}
|
|
203
224
|
<div class="pw-card fluid margin">
|
|
204
225
|
<div class="pw-card-header">Reply to thread</div>
|
|
205
226
|
<div class="pw-card-content">
|
|
@@ -229,6 +250,5 @@
|
|
|
229
250
|
</div>
|
|
230
251
|
</div>
|
|
231
252
|
{% endif %}
|
|
232
|
-
{% endif %}
|
|
233
253
|
|
|
234
254
|
{% endblock %}
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
{{ form.non_field_errors }}
|
|
43
43
|
{% endif %}
|
|
44
44
|
<div class="threadForm__actions">
|
|
45
|
+
<a class="pw-button default" href="{{subcategory.get_absolute_url}}" type="submit">Cancel</a>
|
|
45
46
|
<button class="pw-button raised primary" type="submit">Create Thread</button>
|
|
46
47
|
</div>
|
|
47
48
|
</form>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
punkweb_bb/tests.py
CHANGED
|
@@ -299,14 +299,14 @@ class IndexViewTestCase(TestCase):
|
|
|
299
299
|
username="staff", password="staff", is_staff=True
|
|
300
300
|
)
|
|
301
301
|
|
|
302
|
-
def
|
|
302
|
+
def test_members_online(self):
|
|
303
303
|
response = self.client.get(self.url)
|
|
304
|
-
self.assertEqual(len(response.context["
|
|
304
|
+
self.assertEqual(len(response.context["members_online"]), 0)
|
|
305
305
|
|
|
306
306
|
self.client.force_login(self.user)
|
|
307
307
|
response = self.client.get(self.url)
|
|
308
308
|
|
|
309
|
-
self.assertEqual(len(response.context["
|
|
309
|
+
self.assertEqual(len(response.context["members_online"]), 1)
|
|
310
310
|
|
|
311
311
|
def test_staff_online(self):
|
|
312
312
|
response = self.client.get(self.url)
|
|
@@ -317,6 +317,17 @@ class IndexViewTestCase(TestCase):
|
|
|
317
317
|
|
|
318
318
|
self.assertEqual(len(response.context["staff_online"]), 1)
|
|
319
319
|
|
|
320
|
+
def test_guests_online(self):
|
|
321
|
+
response = self.client.get(self.url)
|
|
322
|
+
self.assertEqual(response.context["guests_online"], 1)
|
|
323
|
+
|
|
324
|
+
def test_total_online(self):
|
|
325
|
+
response = self.client.get(self.url)
|
|
326
|
+
self.client.force_login(self.user)
|
|
327
|
+
response = self.client.get(self.url)
|
|
328
|
+
|
|
329
|
+
self.assertEqual(response.context["total_online"], 2)
|
|
330
|
+
|
|
320
331
|
def test_newest_user(self):
|
|
321
332
|
response = self.client.get(self.url)
|
|
322
333
|
self.assertEqual(response.context["newest_user"], self.staff_user)
|
|
@@ -463,7 +474,7 @@ class ThreadCreateViewTestCase(TestCase):
|
|
|
463
474
|
self.client.force_login(self.user)
|
|
464
475
|
response = self.client.get(self.staff_only_url)
|
|
465
476
|
|
|
466
|
-
self.
|
|
477
|
+
self.assertEqual(response.status_code, 403)
|
|
467
478
|
|
|
468
479
|
|
|
469
480
|
class ThreadViewTestCase(TestCase):
|
|
@@ -511,7 +522,7 @@ class ThreadUpdateViewTestCase(TestCase):
|
|
|
511
522
|
def test_is_author(self):
|
|
512
523
|
self.client.force_login(self.other_user)
|
|
513
524
|
response = self.client.get(self.url)
|
|
514
|
-
self.assertEqual(response.status_code,
|
|
525
|
+
self.assertEqual(response.status_code, 403)
|
|
515
526
|
|
|
516
527
|
self.client.force_login(self.user)
|
|
517
528
|
response = self.client.get(self.url)
|
|
@@ -560,7 +571,7 @@ class ThreadDeleteViewTestCase(TestCase):
|
|
|
560
571
|
def test_is_author(self):
|
|
561
572
|
self.client.force_login(self.other_user)
|
|
562
573
|
response = self.client.get(self.url)
|
|
563
|
-
self.assertEqual(response.status_code,
|
|
574
|
+
self.assertEqual(response.status_code, 403)
|
|
564
575
|
|
|
565
576
|
self.client.force_login(self.user)
|
|
566
577
|
response = self.client.get(self.url)
|
|
@@ -642,7 +653,7 @@ class PostUpdateViewTestCase(TestCase):
|
|
|
642
653
|
def test_is_author(self):
|
|
643
654
|
self.client.force_login(self.other_user)
|
|
644
655
|
response = self.client.get(self.url)
|
|
645
|
-
self.assertEqual(response.status_code,
|
|
656
|
+
self.assertEqual(response.status_code, 403)
|
|
646
657
|
|
|
647
658
|
self.client.force_login(self.user)
|
|
648
659
|
response = self.client.get(self.url)
|
|
@@ -692,7 +703,7 @@ class PostDeleteViewTestCase(TestCase):
|
|
|
692
703
|
def test_is_author(self):
|
|
693
704
|
self.client.force_login(self.other_user)
|
|
694
705
|
response = self.client.get(self.url)
|
|
695
|
-
self.assertEqual(response.status_code,
|
|
706
|
+
self.assertEqual(response.status_code, 403)
|
|
696
707
|
|
|
697
708
|
self.client.force_login(self.user)
|
|
698
709
|
response = self.client.get(self.url)
|
punkweb_bb/urls.py
CHANGED
|
@@ -11,11 +11,37 @@ urlpatterns = [
|
|
|
11
11
|
path("settings/", views.settings_view, name="settings"),
|
|
12
12
|
path("members/", views.members_view, name="members"),
|
|
13
13
|
path("members/<path:user_id>/", views.profile_view, name="profile"),
|
|
14
|
+
path("create-category/", views.category_create_view, name="category_create"),
|
|
15
|
+
path(
|
|
16
|
+
"category/<str:category_slug>/update/",
|
|
17
|
+
views.category_update_view,
|
|
18
|
+
name="category_update",
|
|
19
|
+
),
|
|
20
|
+
path(
|
|
21
|
+
"category/<str:category_slug>/delete/",
|
|
22
|
+
views.category_delete_view,
|
|
23
|
+
name="category_delete",
|
|
24
|
+
),
|
|
14
25
|
path(
|
|
15
26
|
"subcategory/<str:subcategory_slug>/",
|
|
16
27
|
views.subcategory_view,
|
|
17
28
|
name="subcategory",
|
|
18
29
|
),
|
|
30
|
+
path(
|
|
31
|
+
"category/<str:category_slug>/create-subcategory/",
|
|
32
|
+
views.subcategory_create_view,
|
|
33
|
+
name="subcategory_create",
|
|
34
|
+
),
|
|
35
|
+
path(
|
|
36
|
+
"subcategory/<str:subcategory_slug>/update/",
|
|
37
|
+
views.subcategory_update_view,
|
|
38
|
+
name="subcategory_update",
|
|
39
|
+
),
|
|
40
|
+
path(
|
|
41
|
+
"subcategory/<str:subcategory_slug>/delete/",
|
|
42
|
+
views.subcategory_delete_view,
|
|
43
|
+
name="subcategory_delete",
|
|
44
|
+
),
|
|
19
45
|
path(
|
|
20
46
|
"subcategory/<str:subcategory_slug>/create-thread/",
|
|
21
47
|
views.thread_create_view,
|
|
@@ -37,5 +63,6 @@ urlpatterns = [
|
|
|
37
63
|
path("post/<str:post_id>/update/", views.post_update_view, name="post_update"),
|
|
38
64
|
path("shout-list/", views.shout_list_view, name="shout_list"),
|
|
39
65
|
path("shout-create/", views.shout_create_view, name="shout_create"),
|
|
66
|
+
path("shout/<str:shout_id>/delete/", views.shout_delete_view, name="shout_delete"),
|
|
40
67
|
path("bbcode/", views.bbcode_view, name="bbcode"),
|
|
41
68
|
]
|
punkweb_bb/utils.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from django.utils.text import slugify
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_unique_slug(model, field):
|
|
5
|
+
base_slug = slugify(field)
|
|
6
|
+
slug = base_slug
|
|
7
|
+
unique_slug_exists = True
|
|
8
|
+
|
|
9
|
+
counter = 1
|
|
10
|
+
while unique_slug_exists:
|
|
11
|
+
if model.objects.filter(slug=slug).exists():
|
|
12
|
+
slug = f"{base_slug}-{counter}"
|
|
13
|
+
counter += 1
|
|
14
|
+
else:
|
|
15
|
+
unique_slug_exists = False
|
|
16
|
+
|
|
17
|
+
return slug
|