punkweb-bb 0.1.2__py3-none-any.whl → 0.1.4__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.
Files changed (32) hide show
  1. punkweb_bb/__pycache__/guests.cpython-311.pyc +0 -0
  2. punkweb_bb/__pycache__/middleware.cpython-311.pyc +0 -0
  3. punkweb_bb/__pycache__/models.cpython-311.pyc +0 -0
  4. punkweb_bb/__pycache__/settings.cpython-311.pyc +0 -0
  5. punkweb_bb/__pycache__/tests.cpython-311.pyc +0 -0
  6. punkweb_bb/__pycache__/views.cpython-311.pyc +0 -0
  7. punkweb_bb/guests.py +20 -0
  8. punkweb_bb/middleware.py +7 -0
  9. punkweb_bb/migrations/0002_thread_view_count.py +18 -0
  10. punkweb_bb/migrations/__pycache__/0002_thread_view_count.cpython-311.pyc +0 -0
  11. punkweb_bb/models.py +4 -0
  12. punkweb_bb/settings.py +4 -0
  13. punkweb_bb/static/punkweb_bb/css/profile.css +7 -0
  14. punkweb_bb/static/punkweb_bb/css/punkweb.css +23 -0
  15. punkweb_bb/templates/punkweb_bb/base.html +1 -1
  16. punkweb_bb/templates/punkweb_bb/index.html +19 -6
  17. punkweb_bb/templates/punkweb_bb/subcategory.html +7 -1
  18. punkweb_bb/templates/punkweb_bb/thread.html +5 -2
  19. punkweb_bb/templates/punkweb_bb/thread_create.html +3 -0
  20. punkweb_bb/templates/punkweb_bb/thread_update.html +3 -0
  21. punkweb_bb/templatetags/__pycache__/__init__.cpython-311.pyc +0 -0
  22. punkweb_bb/templatetags/__pycache__/humanize_count.cpython-311.pyc +0 -0
  23. punkweb_bb/templatetags/__pycache__/humanize_int.cpython-311.pyc +0 -0
  24. punkweb_bb/templatetags/humanize_int.py +12 -0
  25. punkweb_bb/tests.py +529 -2
  26. punkweb_bb/views.py +20 -4
  27. punkweb_bb-0.1.4.dist-info/METADATA +175 -0
  28. {punkweb_bb-0.1.2.dist-info → punkweb_bb-0.1.4.dist-info}/RECORD +31 -23
  29. punkweb_bb-0.1.2.dist-info/METADATA +0 -72
  30. {punkweb_bb-0.1.2.dist-info → punkweb_bb-0.1.4.dist-info}/LICENSE +0 -0
  31. {punkweb_bb-0.1.2.dist-info → punkweb_bb-0.1.4.dist-info}/WHEEL +0 -0
  32. {punkweb_bb-0.1.2.dist-info → punkweb_bb-0.1.4.dist-info}/top_level.txt +0 -0
punkweb_bb/tests.py CHANGED
@@ -2,7 +2,9 @@ import math
2
2
 
3
3
  from django.contrib.auth import get_user_model
4
4
  from django.core.cache import cache
5
- from django.test import TestCase
5
+ from django.forms import ValidationError
6
+ from django.test import Client, TestCase
7
+ from django.urls import reverse
6
8
  from django.utils import timezone
7
9
 
8
10
  from punkweb_bb.models import (
@@ -141,7 +143,7 @@ class ThreadTestCase(TestCase):
141
143
  self.user = User.objects.create_user(username="test", password="test")
142
144
  self.category = Category.objects.create(name="test")
143
145
  self.subcategory = Subcategory.objects.create(
144
- name="test", category=self.category
146
+ name="test", category=self.category, slug="test"
145
147
  )
146
148
 
147
149
  def test_thread_str(self):
@@ -175,6 +177,64 @@ class ThreadTestCase(TestCase):
175
177
 
176
178
  self.assertEqual(thread.latest_post, post_2)
177
179
 
180
+ def test_last_post_created_at(self):
181
+ thread = Thread.objects.create(
182
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
183
+ )
184
+ initial_last_post_created_at = thread.last_post_created_at
185
+ Post.objects.create(thread=thread, user=self.user, content="test")
186
+ new_last_post_created_at = thread.last_post_created_at
187
+
188
+ self.assertGreater(new_last_post_created_at, initial_last_post_created_at)
189
+
190
+ def test_is_closed(self):
191
+ thread = Thread.objects.create(
192
+ subcategory=self.subcategory,
193
+ user=self.user,
194
+ title="test",
195
+ content="test",
196
+ is_closed=True,
197
+ )
198
+ self.assertEqual(thread.is_closed, True)
199
+
200
+ post = Post(
201
+ thread=thread,
202
+ user=self.user,
203
+ content="test",
204
+ )
205
+
206
+ self.assertRaises(ValidationError, post.save)
207
+
208
+ def test_is_pinned(self):
209
+ thread = Thread.objects.create(
210
+ subcategory=self.subcategory,
211
+ user=self.user,
212
+ title="test1",
213
+ content="test1",
214
+ is_pinned=True,
215
+ )
216
+ self.assertEqual(thread.is_pinned, True)
217
+
218
+ Thread.objects.create(
219
+ subcategory=self.subcategory, user=self.user, title="test2", content="test2"
220
+ )
221
+
222
+ threads = Thread.objects.all()
223
+
224
+ self.assertEqual(threads[0], thread)
225
+
226
+ def test_bump(self):
227
+ thread1 = Thread.objects.create(
228
+ subcategory=self.subcategory, user=self.user, title="test1", content="test1"
229
+ )
230
+ Thread.objects.create(
231
+ subcategory=self.subcategory, user=self.user, title="test2", content="test2"
232
+ )
233
+ Post.objects.create(thread=thread1, user=self.user, content="test1")
234
+ threads = Thread.objects.all()
235
+
236
+ self.assertEqual(threads[0], thread1)
237
+
178
238
  def test_get_absolute_url(self):
179
239
  thread = Thread.objects.create(
180
240
  subcategory=self.subcategory, user=self.user, title="test", content="test"
@@ -228,3 +288,470 @@ class ShoutTestCase(TestCase):
228
288
  def test_str(self):
229
289
  shout = Shout.objects.create(user=self.user, content="test")
230
290
  self.assertEqual(str(shout), f"{shout.user} > {shout.created_at}")
291
+
292
+
293
+ class IndexViewTestCase(TestCase):
294
+ def setUp(self):
295
+ self.client = Client()
296
+ self.url = reverse("punkweb_bb:index")
297
+ self.user = User.objects.create(username="test", password="test")
298
+ self.staff_user = User.objects.create(
299
+ username="staff", password="staff", is_staff=True
300
+ )
301
+
302
+ def test_members_online(self):
303
+ response = self.client.get(self.url)
304
+ self.assertEqual(len(response.context["members_online"]), 0)
305
+
306
+ self.client.force_login(self.user)
307
+ response = self.client.get(self.url)
308
+
309
+ self.assertEqual(len(response.context["members_online"]), 1)
310
+
311
+ def test_staff_online(self):
312
+ response = self.client.get(self.url)
313
+ self.assertEqual(len(response.context["staff_online"]), 0)
314
+
315
+ self.client.force_login(self.staff_user)
316
+ response = self.client.get(self.url)
317
+
318
+ self.assertEqual(len(response.context["staff_online"]), 1)
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
+
331
+ def test_newest_user(self):
332
+ response = self.client.get(self.url)
333
+ self.assertEqual(response.context["newest_user"], self.staff_user)
334
+
335
+ def test_users_count(self):
336
+ response = self.client.get(self.url)
337
+ self.assertEqual(response.context["users"].count(), 2)
338
+
339
+
340
+ class LoginViewTestCase(TestCase):
341
+ def setUp(self):
342
+ self.client = Client()
343
+ self.url = reverse("punkweb_bb:login")
344
+ self.user = User.objects.create_user(username="test", password="test")
345
+
346
+ def test_redirect_authenticated_user(self):
347
+ self.client.force_login(self.user)
348
+ response = self.client.get(self.url)
349
+
350
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
351
+
352
+ def test_login(self):
353
+ response = self.client.post(
354
+ self.url, {"username": "test", "password": "test"}, follow=True
355
+ )
356
+
357
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
358
+ self.assertTrue(response.context["user"].is_authenticated)
359
+
360
+
361
+ class LogoutViewTestCase(TestCase):
362
+ def setUp(self):
363
+ self.client = Client()
364
+ self.url = reverse("punkweb_bb:logout")
365
+ self.user = User.objects.create_user(username="test", password="test")
366
+
367
+ def test_logout(self):
368
+ self.client.force_login(self.user)
369
+ response = self.client.get(self.url, follow=True)
370
+
371
+ self.assertRedirects(response, reverse("punkweb_bb:login"))
372
+ self.assertFalse(response.context["user"].is_authenticated)
373
+
374
+
375
+ class SignupViewTestCase(TestCase):
376
+ def setUp(self):
377
+ self.client = Client()
378
+ self.url = reverse("punkweb_bb:signup")
379
+ self.user = User.objects.create_user(username="test1", password="test")
380
+
381
+ def test_redirect_authenticated_user(self):
382
+ self.client.force_login(self.user)
383
+ response = self.client.get(self.url)
384
+
385
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
386
+
387
+ def test_signup(self):
388
+ response = self.client.post(
389
+ self.url,
390
+ {
391
+ "username": "test2",
392
+ "password1": "needsmorecomplexity",
393
+ "password2": "needsmorecomplexity",
394
+ },
395
+ )
396
+
397
+ self.assertRedirects(response, reverse("punkweb_bb:login"))
398
+
399
+
400
+ class SettingsViewTestCase(TestCase):
401
+ def setUp(self):
402
+ self.client = Client()
403
+ self.url = reverse("punkweb_bb:settings")
404
+ self.user = User.objects.create_user(username="test", password="test")
405
+
406
+ def test_redirect_unauthenticated_user(self):
407
+ response = self.client.get(self.url)
408
+
409
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
410
+
411
+ def test_settings(self):
412
+ self.client.force_login(self.user)
413
+ response = self.client.get(self.url)
414
+
415
+ self.assertEqual(response.status_code, 200)
416
+
417
+ self.client.post(
418
+ self.url,
419
+ {
420
+ "signature": "[b]test[/b]",
421
+ },
422
+ )
423
+
424
+ self.user.profile.refresh_from_db()
425
+ self.assertEqual(self.user.profile._signature_rendered, "<strong>test</strong>")
426
+
427
+ self.assertEqual(response.status_code, 200)
428
+
429
+
430
+ class ThreadCreateViewTestCase(TestCase):
431
+ def setUp(self):
432
+ self.client = Client()
433
+ self.user = User.objects.create_user(username="test", password="test")
434
+ self.category = Category.objects.create(name="test")
435
+ self.subcategory = Subcategory.objects.create(
436
+ name="test", category=self.category, slug="test"
437
+ )
438
+ self.staff_subcategory = Subcategory.objects.create(
439
+ name="staff", category=self.category, slug="staff", staff_post_only=True
440
+ )
441
+ self.url = reverse("punkweb_bb:thread_create", args=[self.subcategory.slug])
442
+ self.staff_only_url = reverse(
443
+ "punkweb_bb:thread_create", args=[self.staff_subcategory.slug]
444
+ )
445
+
446
+ def test_redirect_unauthenticated_user(self):
447
+ response = self.client.get(self.url)
448
+
449
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
450
+
451
+ def test_thread_create(self):
452
+ self.client.force_login(self.user)
453
+ response = self.client.get(self.url)
454
+
455
+ self.assertEqual(response.status_code, 200)
456
+
457
+ response = self.client.post(
458
+ self.url,
459
+ {
460
+ "title": "test",
461
+ "content": "test",
462
+ },
463
+ follow=True,
464
+ )
465
+
466
+ new_thread = Thread.objects.first()
467
+
468
+ self.assertRedirects(response, new_thread.get_absolute_url())
469
+ self.assertEqual(Thread.objects.count(), 1)
470
+ self.assertEqual(new_thread.user, self.user)
471
+ self.assertEqual(new_thread.subcategory, self.subcategory)
472
+
473
+ def test_thread_create_staff_post_only(self):
474
+ self.client.force_login(self.user)
475
+ response = self.client.get(self.staff_only_url)
476
+
477
+ self.assertRedirects(response, self.staff_subcategory.get_absolute_url())
478
+
479
+
480
+ class ThreadViewTestCase(TestCase):
481
+ def setUp(self):
482
+ self.client = Client()
483
+ self.user = User.objects.create_user(username="test", password="test")
484
+ self.category = Category.objects.create(name="test")
485
+ self.subcategory = Subcategory.objects.create(
486
+ name="test", category=self.category, slug="test"
487
+ )
488
+ self.thread = Thread.objects.create(
489
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
490
+ )
491
+ self.url = reverse("punkweb_bb:thread", args=[self.thread.id])
492
+
493
+ def test_view_count(self):
494
+ response = self.client.get(self.url)
495
+ self.assertEqual(response.context["thread"].view_count, 1)
496
+
497
+ # ensure that the view count does not increase when viewed again from the same session
498
+
499
+ response = self.client.get(self.url)
500
+ self.assertEqual(response.context["thread"].view_count, 1)
501
+
502
+
503
+ class ThreadUpdateViewTestCase(TestCase):
504
+ def setUp(self):
505
+ self.client = Client()
506
+ self.user = User.objects.create_user(username="test", password="test")
507
+ self.other_user = User.objects.create_user(username="other", password="other")
508
+ self.category = Category.objects.create(name="test")
509
+ self.subcategory = Subcategory.objects.create(
510
+ name="test", category=self.category, slug="test"
511
+ )
512
+ self.thread = Thread.objects.create(
513
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
514
+ )
515
+ self.url = reverse("punkweb_bb:thread_update", args=[self.thread.id])
516
+
517
+ def test_redirect_unauthenticated_user(self):
518
+ response = self.client.get(self.url)
519
+
520
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
521
+
522
+ def test_is_author(self):
523
+ self.client.force_login(self.other_user)
524
+ response = self.client.get(self.url)
525
+ self.assertEqual(response.status_code, 404)
526
+
527
+ self.client.force_login(self.user)
528
+ response = self.client.get(self.url)
529
+ self.assertEqual(response.status_code, 200)
530
+
531
+ def test_thread_update(self):
532
+ self.client.force_login(self.user)
533
+ response = self.client.get(self.url)
534
+
535
+ self.assertEqual(response.status_code, 200)
536
+
537
+ response = self.client.post(
538
+ self.url,
539
+ {
540
+ "title": "edit",
541
+ "content": "edit",
542
+ },
543
+ follow=True,
544
+ )
545
+
546
+ self.assertRedirects(response, self.thread.get_absolute_url())
547
+ self.thread.refresh_from_db()
548
+ self.assertEqual(self.thread.title, "edit")
549
+ self.assertEqual(self.thread._content_rendered, "edit")
550
+
551
+
552
+ class ThreadDeleteViewTestCase(TestCase):
553
+ def setUp(self):
554
+ self.client = Client()
555
+ self.user = User.objects.create_user(username="test", password="test")
556
+ self.other_user = User.objects.create_user(username="other", password="other")
557
+ self.category = Category.objects.create(name="test")
558
+ self.subcategory = Subcategory.objects.create(
559
+ name="test", category=self.category, slug="test"
560
+ )
561
+ self.thread = Thread.objects.create(
562
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
563
+ )
564
+ self.url = reverse("punkweb_bb:thread_delete", args=[self.thread.id])
565
+
566
+ def test_redirect_unauthenticated_user(self):
567
+ response = self.client.get(self.url)
568
+
569
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
570
+
571
+ def test_is_author(self):
572
+ self.client.force_login(self.other_user)
573
+ response = self.client.get(self.url)
574
+ self.assertEqual(response.status_code, 404)
575
+
576
+ self.client.force_login(self.user)
577
+ response = self.client.get(self.url)
578
+ self.assertEqual(response.status_code, 200)
579
+
580
+ def test_thread_delete(self):
581
+ self.client.force_login(self.user)
582
+ response = self.client.get(self.url)
583
+
584
+ self.assertEqual(response.status_code, 200)
585
+
586
+ response = self.client.delete(self.url, follow=True)
587
+
588
+ self.assertEqual(
589
+ response.headers["HX-Redirect"], self.subcategory.get_absolute_url()
590
+ )
591
+ self.assertEqual(Thread.objects.count(), 0)
592
+
593
+
594
+ class PostCreateViewTestCase(TestCase):
595
+ def setUp(self):
596
+ self.client = Client()
597
+ self.user = User.objects.create_user(username="test", password="test")
598
+ self.category = Category.objects.create(name="test")
599
+ self.subcategory = Subcategory.objects.create(
600
+ name="test", category=self.category, slug="test"
601
+ )
602
+ self.thread = Thread.objects.create(
603
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
604
+ )
605
+ self.url = reverse("punkweb_bb:post_create", args=[self.thread.id])
606
+
607
+ def test_redirect_unauthenticated_user(self):
608
+ response = self.client.get(self.url)
609
+
610
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
611
+
612
+ def test_post_create(self):
613
+ self.client.force_login(self.user)
614
+
615
+ response = self.client.post(
616
+ self.url,
617
+ {
618
+ "content": "test",
619
+ },
620
+ follow=True,
621
+ )
622
+
623
+ new_post = Post.objects.first()
624
+
625
+ self.assertRedirects(response, new_post.get_absolute_url())
626
+ self.assertEqual(Post.objects.count(), 1)
627
+ self.assertEqual(new_post.user, self.user)
628
+ self.assertEqual(new_post.thread, self.thread)
629
+
630
+
631
+ class PostUpdateViewTestCase(TestCase):
632
+ def setUp(self):
633
+ self.client = Client()
634
+ self.user = User.objects.create_user(username="test", password="test")
635
+ self.other_user = User.objects.create_user(username="other", password="other")
636
+ self.category = Category.objects.create(name="test")
637
+ self.subcategory = Subcategory.objects.create(
638
+ name="test", category=self.category, slug="test"
639
+ )
640
+ self.thread = Thread.objects.create(
641
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
642
+ )
643
+ self.post = Post.objects.create(
644
+ thread=self.thread, user=self.user, content="test"
645
+ )
646
+ self.url = reverse("punkweb_bb:post_update", args=[self.post.id])
647
+
648
+ def test_redirect_unauthenticated_user(self):
649
+ response = self.client.get(self.url)
650
+
651
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
652
+
653
+ def test_is_author(self):
654
+ self.client.force_login(self.other_user)
655
+ response = self.client.get(self.url)
656
+ self.assertEqual(response.status_code, 404)
657
+
658
+ self.client.force_login(self.user)
659
+ response = self.client.get(self.url)
660
+ self.assertEqual(response.status_code, 200)
661
+
662
+ def test_post_update(self):
663
+ self.client.force_login(self.user)
664
+ response = self.client.get(self.url)
665
+
666
+ self.assertEqual(response.status_code, 200)
667
+
668
+ response = self.client.post(
669
+ self.url,
670
+ {
671
+ "content": "edit",
672
+ },
673
+ follow=True,
674
+ )
675
+
676
+ self.assertRedirects(response, self.post.get_absolute_url())
677
+ self.post.refresh_from_db()
678
+ self.assertEqual(self.post._content_rendered, "edit")
679
+
680
+
681
+ class PostDeleteViewTestCase(TestCase):
682
+ def setUp(self):
683
+ self.client = Client()
684
+ self.user = User.objects.create_user(username="test", password="test")
685
+ self.other_user = User.objects.create_user(username="other", password="other")
686
+ self.category = Category.objects.create(name="test")
687
+ self.subcategory = Subcategory.objects.create(
688
+ name="test", category=self.category, slug="test"
689
+ )
690
+ self.thread = Thread.objects.create(
691
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
692
+ )
693
+ self.post = Post.objects.create(
694
+ thread=self.thread, user=self.user, content="test"
695
+ )
696
+ self.url = reverse("punkweb_bb:post_delete", args=[self.post.id])
697
+
698
+ def test_redirect_unauthenticated_user(self):
699
+ response = self.client.get(self.url)
700
+
701
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
702
+
703
+ def test_is_author(self):
704
+ self.client.force_login(self.other_user)
705
+ response = self.client.get(self.url)
706
+ self.assertEqual(response.status_code, 404)
707
+
708
+ self.client.force_login(self.user)
709
+ response = self.client.get(self.url)
710
+ self.assertEqual(response.status_code, 200)
711
+
712
+ def test_post_delete(self):
713
+ self.client.force_login(self.user)
714
+ response = self.client.get(self.url)
715
+
716
+ self.assertEqual(response.status_code, 200)
717
+
718
+ response = self.client.delete(self.url, follow=True)
719
+
720
+ self.assertEqual(
721
+ response.headers["HX-Redirect"], self.thread.get_absolute_url()
722
+ )
723
+ self.assertEqual(Post.objects.count(), 0)
724
+
725
+
726
+ class ShoutCreateViewTestCase(TestCase):
727
+ def setUp(self):
728
+ self.client = Client()
729
+ self.user = User.objects.create_user(username="test", password="test")
730
+ self.url = reverse("punkweb_bb:shout_create")
731
+
732
+ def test_unauthenticated(self):
733
+ response = self.client.get(self.url)
734
+
735
+ self.client.post(
736
+ self.url,
737
+ {
738
+ "content": "test",
739
+ },
740
+ )
741
+
742
+ self.assertEqual(Shout.objects.count(), 0)
743
+ self.assertEqual(response.status_code, 200)
744
+
745
+ def test_shout_create(self):
746
+ self.client.force_login(self.user)
747
+
748
+ response = self.client.post(
749
+ self.url,
750
+ {
751
+ "content": "test",
752
+ },
753
+ follow=True,
754
+ )
755
+
756
+ self.assertEqual(Shout.objects.count(), 1)
757
+ self.assertEqual(response.status_code, 200)
punkweb_bb/views.py CHANGED
@@ -6,6 +6,7 @@ from django.http import HttpResponseForbidden
6
6
  from django.shortcuts import get_object_or_404, redirect, render
7
7
  from django.utils import timezone
8
8
 
9
+ from punkweb_bb.guests import guest_list
9
10
  from punkweb_bb.forms import (
10
11
  BoardProfileModelForm,
11
12
  LoginForm,
@@ -31,8 +32,12 @@ def index_view(request):
31
32
 
32
33
  users = User.objects.select_related("profile").all()
33
34
  newest_user = users.order_by("-profile__created_at").first()
35
+
34
36
  users_online = [user for user in users if user.profile.is_online]
37
+ members_online = [user for user in users_online if not user.is_staff]
35
38
  staff_online = [user for user in users_online if user.is_staff]
39
+ guests_online = guest_list.length()
40
+ total_online = len(members_online) + len(staff_online) + guests_online
36
41
 
37
42
  context = {
38
43
  "categories": categories,
@@ -41,8 +46,10 @@ def index_view(request):
41
46
  "post_count": post_count,
42
47
  "users": users,
43
48
  "newest_user": newest_user,
44
- "users_online": users_online,
49
+ "members_online": members_online,
45
50
  "staff_online": staff_online,
51
+ "guests_online": guests_online,
52
+ "total_online": total_online,
46
53
  }
47
54
  return render(request, "punkweb_bb/index.html", context=context)
48
55
 
@@ -108,7 +115,9 @@ def profile_view(request, user_id):
108
115
 
109
116
 
110
117
  def members_view(request):
111
- users = paginate_qs(request, User.objects.select_related("profile").all())
118
+ users = paginate_qs(
119
+ request, User.objects.select_related("profile").order_by("username")
120
+ )
112
121
 
113
122
  context = {
114
123
  "users": users,
@@ -185,6 +194,13 @@ def thread_view(request, thread_id):
185
194
 
186
195
  post_form = PostModelForm()
187
196
 
197
+ # Increment view count if this session hasn't viewed the thread before
198
+ viewed_threads = request.session.get("viewed_threads", [])
199
+ if thread_id not in viewed_threads:
200
+ thread.view_count += 1
201
+ thread.save()
202
+ request.session["viewed_threads"] = viewed_threads + [thread_id]
203
+
188
204
  context = {
189
205
  "thread": thread,
190
206
  "posts": posts,
@@ -235,7 +251,7 @@ def post_create_view(request, thread_id):
235
251
  thread = get_object_or_404(Thread, pk=thread_id)
236
252
 
237
253
  if thread.is_closed:
238
- return HttpResponseForbidden("This thread is closed.")
254
+ return HttpResponseForbidden("Cannot add posts to a closed thread.")
239
255
 
240
256
  form = PostModelForm(request.POST)
241
257
 
@@ -336,7 +352,7 @@ def bbcode_view(request):
336
352
  ("Url", "[url=https://google.com]Link Text[/url]"),
337
353
  (
338
354
  "Image",
339
- "[img]https://punkweb.net/media/music/artists/system-lynx_EklOGpj.png.200x200_q85_crop.png[/img]",
355
+ "[img]https://placehold.co/400[/img]",
340
356
  ),
341
357
  # Custom
342
358
  ("Horizontal Rule", "[hr]"),