Browse Source

another code cleanup, made links consistent with current DRF and Django's practices

Rafał Pitoń 9 years ago
parent
commit
279c150d7a
99 changed files with 627 additions and 693 deletions
  1. 18 15
      misago/acl/admin.py
  2. 4 4
      misago/acl/tests/test_roleadmin_views.py
  3. 6 4
      misago/admin/admin.py
  4. 1 1
      misago/admin/urls.py
  5. 8 10
      misago/categories/admin.py
  6. 2 2
      misago/categories/categorytypes.py
  7. 2 2
      misago/categories/serializers.py
  8. 42 28
      misago/categories/tests/test_categories_admin_views.py
  9. 23 16
      misago/categories/tests/test_permissions_admin_views.py
  10. 7 5
      misago/conf/admin.py
  11. 6 4
      misago/conf/tests/test_admin_views.py
  12. 3 3
      misago/conf/views.py
  13. 1 1
      misago/core/exceptionhandler.py
  14. 1 1
      misago/core/templatetags/misago_capture.py
  15. 13 13
      misago/core/testproject/urls.py
  16. 3 3
      misago/core/testproject/views.py
  17. 2 2
      misago/core/tests/test_decorators.py
  18. 9 9
      misago/core/tests/test_errorpages.py
  19. 2 2
      misago/core/tests/test_mailer.py
  20. 6 6
      misago/core/tests/test_page.py
  21. 12 10
      misago/core/tests/test_shortcuts.py
  22. 1 1
      misago/core/tests/test_templatetags.py
  23. 1 1
      misago/core/tests/test_views.py
  24. 2 2
      misago/legal/context_processors.py
  25. 8 8
      misago/legal/tests.py
  26. 2 2
      misago/legal/urls.py
  27. 1 1
      misago/templates/misago/activation/error.html
  28. 3 3
      misago/templates/misago/admin/bans/list.html
  29. 5 5
      misago/templates/misago/admin/categories/list.html
  30. 2 2
      misago/templates/misago/admin/categoryroles/list.html
  31. 2 2
      misago/templates/misago/admin/conf/index.html
  32. 1 1
      misago/templates/misago/admin/index.html
  33. 0 62
      misago/templates/misago/admin/labels/form.html
  34. 0 70
      misago/templates/misago/admin/labels/list.html
  35. 1 1
      misago/templates/misago/admin/navbar.html
  36. 7 7
      misago/templates/misago/admin/ranks/list.html
  37. 4 4
      misago/templates/misago/admin/roles/list.html
  38. 3 3
      misago/templates/misago/admin/users/delete.html
  39. 2 2
      misago/templates/misago/admin/users/list.html
  40. 5 5
      misago/templates/misago/admin/warnings/list.html
  41. 1 1
      misago/templates/misago/categories/last_activity.html
  42. 1 1
      misago/templates/misago/emails/activation/by_user.html
  43. 1 1
      misago/templates/misago/emails/activation/by_user.txt
  44. 1 1
      misago/templates/misago/emails/change_email.html
  45. 1 1
      misago/templates/misago/emails/change_email.txt
  46. 1 1
      misago/templates/misago/emails/change_password.html
  47. 1 1
      misago/templates/misago/emails/change_password.txt
  48. 1 1
      misago/templates/misago/emails/change_password_form_link.html
  49. 1 1
      misago/templates/misago/emails/change_password_form_link.txt
  50. 1 1
      misago/templates/misago/emails/register/inactive.html
  51. 1 1
      misago/templates/misago/emails/register/inactive.txt
  52. 2 2
      misago/templates/misago/footer.html
  53. 1 1
      misago/templates/misago/forgottenpassword/error.html
  54. 1 1
      misago/templates/misago/options/credentials_error.html
  55. 1 1
      misago/templates/misago/profile/header.html
  56. 1 1
      misago/templates/misago/profile/nav.html
  57. 2 2
      misago/templates/misago/userslists/active_posters.html
  58. 5 5
      misago/templates/misago/userslists/rank.html
  59. 2 2
      misago/threads/serializers/thread.py
  60. 2 2
      misago/threads/threadtypes/thread.py
  61. 7 7
      misago/threads/urls/__init__.py
  62. 2 2
      misago/threads/views/threadslist.py
  63. 0 1
      misago/urls.py
  64. 68 58
      misago/users/admin.py
  65. 2 2
      misago/users/api/auth.py
  66. 5 4
      misago/users/api/usernamechanges.py
  67. 4 4
      misago/users/api/users.py
  68. 28 27
      misago/users/apps.py
  69. 2 2
      misago/users/authbackends.py
  70. 3 3
      misago/users/avatars/store.py
  71. 3 3
      misago/users/context_processors.py
  72. 2 4
      misago/users/forms/admin.py
  73. 1 3
      misago/users/models/rank.py
  74. 24 17
      misago/users/models/user.py
  75. 3 3
      misago/users/templatetags/misago_avatars.py
  76. 22 20
      misago/users/tests/test_activation_views.py
  77. 47 35
      misago/users/tests/test_auth_api.py
  78. 9 8
      misago/users/tests/test_avatarserver_views.py
  79. 4 4
      misago/users/tests/test_banadmin_views.py
  80. 1 1
      misago/users/tests/test_captcha_api.py
  81. 4 4
      misago/users/tests/test_decorators.py
  82. 23 13
      misago/users/tests/test_forgottenpassword_views.py
  83. 5 6
      misago/users/tests/test_lists_views.py
  84. 3 3
      misago/users/tests/test_options_views.py
  85. 16 16
      misago/users/tests/test_profile_views.py
  86. 9 9
      misago/users/tests/test_rankadmin_views.py
  87. 6 6
      misago/users/tests/test_rest_permissions.py
  88. 4 4
      misago/users/tests/test_user_avatar_api.py
  89. 7 7
      misago/users/tests/test_useradmin_views.py
  90. 0 4
      misago/users/tests/test_users_api.py
  91. 5 5
      misago/users/tests/test_warningadmin_views.py
  92. 23 23
      misago/users/urls/__init__.py
  93. 4 4
      misago/users/urls/api.py
  94. 3 3
      misago/users/views/activation.py
  95. 4 4
      misago/users/views/admin/users.py
  96. 10 10
      misago/users/views/avatarserver.py
  97. 5 5
      misago/users/views/forgottenpassword.py
  98. 5 4
      misago/users/views/lists.py
  99. 5 4
      misago/users/views/profile.py

+ 18 - 15
misago/acl/admin.py

@@ -14,21 +14,24 @@ class MisagoAdminExtension(object):
         urlpatterns.patterns('permissions:users',
         urlpatterns.patterns('permissions:users',
             url(r'^$', RolesList.as_view(), name='index'),
             url(r'^$', RolesList.as_view(), name='index'),
             url(r'^new/$', NewRole.as_view(), name='new'),
             url(r'^new/$', NewRole.as_view(), name='new'),
-            url(r'^edit/(?P<role_id>\d+)/$', EditRole.as_view(), name='edit'),
-            url(r'^users/(?P<role_id>\d+)/$', RoleUsers.as_view(), name='users'),
-            url(r'^delete/(?P<role_id>\d+)/$', DeleteRole.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditRole.as_view(), name='edit'),
+            url(r'^users/(?P<pk>\d+)/$', RoleUsers.as_view(), name='users'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteRole.as_view(), name='delete'),
         )
         )
 
 
     def register_navigation_nodes(self, site):
     def register_navigation_nodes(self, site):
-        site.add_node(name=_("Permissions"),
-                      icon='fa fa-adjust',
-                      parent='misago:admin',
-                      after='misago:admin:users:accounts:index',
-                      namespace='misago:admin:permissions',
-                      link='misago:admin:permissions:users:index')
-
-        site.add_node(name=_("User roles"),
-                      icon='fa fa-th-large',
-                      parent='misago:admin:permissions',
-                      namespace='misago:admin:permissions:users',
-                      link='misago:admin:permissions:users:index')
+        site.add_node(
+            name=_("Permissions"),
+            icon='fa fa-adjust',
+            parent='misago:admin',
+            after='misago:admin:users:accounts:index',
+            namespace='misago:admin:permissions',
+            link='misago:admin:permissions:users:index',
+        )
+        site.add_node(
+            name=_("User roles"),
+            icon='fa fa-th-large',
+            parent='misago:admin:permissions',
+            namespace='misago:admin:permissions:users',
+            link='misago:admin:permissions:users:index',
+        )

+ 4 - 4
misago/acl/tests/test_roleadmin_views.py

@@ -53,13 +53,13 @@ class RoleAdminViewsTests(AdminTestCase):
 
 
         response = self.client.get(
         response = self.client.get(
             reverse('misago:admin:permissions:users:edit',
             reverse('misago:admin:permissions:users:edit',
-                    kwargs={'role_id': test_role.pk}))
+                    kwargs={'pk': test_role.pk}))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test Role', response.content)
         self.assertIn('Test Role', response.content)
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:permissions:users:edit',
             reverse('misago:admin:permissions:users:edit',
-                    kwargs={'role_id': test_role.pk}),
+                    kwargs={'pk': test_role.pk}),
             data=fake_data({'name': 'Top Lel'}))
             data=fake_data({'name': 'Top Lel'}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
@@ -78,7 +78,7 @@ class RoleAdminViewsTests(AdminTestCase):
 
 
         response = self.client.get(
         response = self.client.get(
             reverse('misago:admin:permissions:users:users',
             reverse('misago:admin:permissions:users:users',
-                    kwargs={'role_id': test_role.pk}))
+                    kwargs={'pk': test_role.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
     def test_delete_view(self):
     def test_delete_view(self):
@@ -90,7 +90,7 @@ class RoleAdminViewsTests(AdminTestCase):
         test_role = Role.objects.get(name='Test Role')
         test_role = Role.objects.get(name='Test Role')
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:permissions:users:delete',
             reverse('misago:admin:permissions:users:delete',
-                    kwargs={'role_id': test_role.pk}))
+                    kwargs={'pk': test_role.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:permissions:users:index'))
         self.client.get(reverse('misago:admin:permissions:users:index'))

+ 6 - 4
misago/admin/admin.py

@@ -7,7 +7,9 @@ class MisagoAdminExtension(object):
         pass
         pass
 
 
     def register_navigation_nodes(self, site):
     def register_navigation_nodes(self, site):
-        site.add_node(name=_("Home"),
-                      icon='fa fa-home',
-                      parent='misago:admin',
-                      link='misago:admin:index')
+        site.add_node(
+            name=_("Home"),
+            icon='fa fa-home',
+            parent='misago:admin',
+            link='misago:admin:index',
+        )

+ 1 - 1
misago/admin/urls.py

@@ -7,7 +7,7 @@ urlpatterns = patterns('misago.admin.views',
     # any request with path that falls below this one is assumed to be directed
     # any request with path that falls below this one is assumed to be directed
     # at Misago Admin and will be checked by Misago Admin Middleware
     # at Misago Admin and will be checked by Misago Admin Middleware
     url(r'^$', 'index.admin_index', name='index'),
     url(r'^$', 'index.admin_index', name='index'),
-    url(r'^resolve-version/$', 'index.check_version', name='check_version'),
+    url(r'^resolve-version/$', 'index.check_version', name='check-version'),
     url(r'^logout/$', 'auth.logout', name='logout'),
     url(r'^logout/$', 'auth.logout', name='logout'),
 )
 )
 
 

+ 8 - 10
misago/categories/admin.py

@@ -19,11 +19,11 @@ class MisagoAdminExtension(object):
         urlpatterns.patterns('categories:nodes',
         urlpatterns.patterns('categories:nodes',
             url(r'^$', CategoriesList.as_view(), name='index'),
             url(r'^$', CategoriesList.as_view(), name='index'),
             url(r'^new/$', NewCategory.as_view(), name='new'),
             url(r'^new/$', NewCategory.as_view(), name='new'),
-            url(r'^edit/(?P<category_id>\d+)/$', EditCategory.as_view(), name='edit'),
-            url(r'^permissions/(?P<category_id>\d+)/$', CategoryPermissions.as_view(), name='permissions'),
-            url(r'^move/down/(?P<category_id>\d+)/$', MoveDownCategory.as_view(), name='down'),
-            url(r'^move/up/(?P<category_id>\d+)/$', MoveUpCategory.as_view(), name='up'),
-            url(r'^delete/(?P<category_id>\d+)/$', DeleteCategory.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditCategory.as_view(), name='edit'),
+            url(r'^permissions/(?P<pk>\d+)/$', CategoryPermissions.as_view(), name='permissions'),
+            url(r'^move/down/(?P<pk>\d+)/$', MoveDownCategory.as_view(), name='down'),
+            url(r'^move/up/(?P<pk>\d+)/$', MoveUpCategory.as_view(), name='up'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteCategory.as_view(), name='delete'),
         )
         )
 
 
         # Category Roles
         # Category Roles
@@ -31,13 +31,13 @@ class MisagoAdminExtension(object):
         urlpatterns.patterns('permissions:categories',
         urlpatterns.patterns('permissions:categories',
             url(r'^$', CategoryRolesList.as_view(), name='index'),
             url(r'^$', CategoryRolesList.as_view(), name='index'),
             url(r'^new/$', NewCategoryRole.as_view(), name='new'),
             url(r'^new/$', NewCategoryRole.as_view(), name='new'),
-            url(r'^edit/(?P<role_id>\d+)/$', EditCategoryRole.as_view(), name='edit'),
-            url(r'^delete/(?P<role_id>\d+)/$', DeleteCategoryRole.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditCategoryRole.as_view(), name='edit'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteCategoryRole.as_view(), name='delete'),
         )
         )
 
 
         # Change Role Category Permissions
         # Change Role Category Permissions
         urlpatterns.patterns('permissions:users',
         urlpatterns.patterns('permissions:users',
-            url(r'^categories/(?P<role_id>\d+)/$', RoleCategoriesACL.as_view(), name='categories'),
+            url(r'^categories/(?P<pk>\d+)/$', RoleCategoriesACL.as_view(), name='categories'),
         )
         )
 
 
     def register_navigation_nodes(self, site):
     def register_navigation_nodes(self, site):
@@ -49,7 +49,6 @@ class MisagoAdminExtension(object):
             namespace='misago:admin:categories',
             namespace='misago:admin:categories',
             link='misago:admin:categories:nodes:index'
             link='misago:admin:categories:nodes:index'
         )
         )
-
         site.add_node(
         site.add_node(
             name=_("Categories hierarchy"),
             name=_("Categories hierarchy"),
             icon='fa fa-sitemap',
             icon='fa fa-sitemap',
@@ -57,7 +56,6 @@ class MisagoAdminExtension(object):
             namespace='misago:admin:categories:nodes',
             namespace='misago:admin:categories:nodes',
             link='misago:admin:categories:nodes:index'
             link='misago:admin:categories:nodes:index'
         )
         )
-
         site.add_node(
         site.add_node(
             name=_("Category roles"),
             name=_("Category roles"),
             icon='fa fa-comments-o',
             icon='fa fa-comments-o',

+ 2 - 2
misago/categories/categorytypes.py

@@ -37,8 +37,8 @@ class Category(RootCategory):
 
 
     def get_category_absolute_url(self, category):
     def get_category_absolute_url(self, category):
         return reverse('misago:category', kwargs={
         return reverse('misago:category', kwargs={
-            'category_slug': category.slug,
-            'category_id': category.id,
+            'pk': category.pk,
+            'slug': category.slug,
         })
         })
 
 
     def get_category_api_read_url(self, category):
     def get_category_api_read_url(self, category):

+ 2 - 2
misago/categories/serializers.py

@@ -112,8 +112,8 @@ class CategorySerializer(serializers.ModelSerializer):
     def get_last_poster_url(self, obj):
     def get_last_poster_url(self, obj):
         if obj.last_poster_id:
         if obj.last_poster_id:
             return reverse('misago:user', kwargs={
             return reverse('misago:user', kwargs={
-                'user_slug': obj.last_poster_slug,
-                'user_id': obj.last_poster_id,
+                'slug': obj.last_poster_slug,
+                'pk': obj.last_poster_id,
             })
             })
         else:
         else:
             return None
             return None

+ 42 - 28
misago/categories/tests/test_categories_admin_views.py

@@ -79,13 +79,15 @@ class CategoryAdminViewsTests(AdminTestCase):
         root = Category.objects.root_category()
         root = Category.objects.root_category()
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:edit',
-                    kwargs={'category_id': private_threads.pk}))
+            reverse('misago:admin:categories:nodes:edit', kwargs={
+                'pk': private_threads.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:edit',
-                    kwargs={'category_id': root.pk}))
+            reverse('misago:admin:categories:nodes:edit', kwargs={
+                'pk': root.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         response = self.client.post(
         response = self.client.post(
@@ -101,15 +103,17 @@ class CategoryAdminViewsTests(AdminTestCase):
         test_category = Category.objects.get(slug='test-category')
         test_category = Category.objects.get(slug='test-category')
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:edit',
-                    kwargs={'category_id': test_category.pk}))
+            reverse('misago:admin:categories:nodes:edit', kwargs={
+                'pk': test_category.pk
+            }))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test Category', response.content)
         self.assertIn('Test Category', response.content)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:edit',
-                    kwargs={'category_id': test_category.pk}),
+            reverse('misago:admin:categories:nodes:edit', kwargs={
+                'pk': test_category.pk
+            }),
             data={
             data={
                 'name': 'Test Category Edited',
                 'name': 'Test Category Edited',
                 'new_parent': root.pk,
                 'new_parent': root.pk,
@@ -146,8 +150,9 @@ class CategoryAdminViewsTests(AdminTestCase):
         category_b = Category.objects.get(slug='category-b')
         category_b = Category.objects.get(slug='category-b')
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:up',
-                    kwargs={'category_id': category_b.pk}))
+            reverse('misago:admin:categories:nodes:up', kwargs={
+                'pk': category_b.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:categories:nodes:index'))
         self.client.get(reverse('misago:admin:categories:nodes:index'))
@@ -159,8 +164,9 @@ class CategoryAdminViewsTests(AdminTestCase):
         self.assertTrue(position_a > position_b)
         self.assertTrue(position_a > position_b)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:up',
-                    kwargs={'category_id': category_b.pk}))
+            reverse('misago:admin:categories:nodes:up', kwargs={
+                'pk': category_b.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:categories:nodes:index'))
         self.client.get(reverse('misago:admin:categories:nodes:index'))
@@ -172,8 +178,9 @@ class CategoryAdminViewsTests(AdminTestCase):
         self.assertTrue(position_a > position_b)
         self.assertTrue(position_a > position_b)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:down',
-                    kwargs={'category_id': category_b.pk}))
+            reverse('misago:admin:categories:nodes:down', kwargs={
+                'pk': category_b.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:categories:nodes:index'))
         self.client.get(reverse('misago:admin:categories:nodes:index'))
@@ -185,8 +192,9 @@ class CategoryAdminViewsTests(AdminTestCase):
         self.assertTrue(position_a > position_b)
         self.assertTrue(position_a > position_b)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:down',
-                    kwargs={'category_id': category_b.pk}))
+            reverse('misago:admin:categories:nodes:down', kwargs={
+                'pk': category_b.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:categories:nodes:index'))
         self.client.get(reverse('misago:admin:categories:nodes:index'))
@@ -265,13 +273,15 @@ class CategoryAdminDeleteViewTests(AdminTestCase):
     def test_delete_category_move_contents(self):
     def test_delete_category_move_contents(self):
         """category was deleted and its contents were moved"""
         """category was deleted and its contents were moved"""
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_b.pk}))
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_b.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_b.pk}),
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_b.pk
+            }),
             data={
             data={
                 'move_children_to': self.category_e.pk,
                 'move_children_to': self.category_e.pk,
                 'move_threads_to': self.category_d.pk,
                 'move_threads_to': self.category_d.pk,
@@ -282,13 +292,15 @@ class CategoryAdminDeleteViewTests(AdminTestCase):
     def test_delete_category_and_contents(self):
     def test_delete_category_and_contents(self):
         """category and its contents were deleted"""
         """category and its contents were deleted"""
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_b.pk}))
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_b.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_b.pk}),
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_b.pk
+            }),
             data={'move_children_to': '', 'move_threads_to': ''})
             data={'move_children_to': '', 'move_threads_to': ''})
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
@@ -297,13 +309,15 @@ class CategoryAdminDeleteViewTests(AdminTestCase):
     def test_delete_leaf_category(self):
     def test_delete_leaf_category(self):
         """category was deleted and its contents were moved"""
         """category was deleted and its contents were moved"""
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_b.pk}))
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_b.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:categories:nodes:delete',
-                    kwargs={'category_id': self.category_d.pk}),
+            reverse('misago:admin:categories:nodes:delete', kwargs={
+                'pk': self.category_d.pk
+            }),
             data={
             data={
                 'move_children_to': '',
                 'move_children_to': '',
                 'move_threads_to': '',
                 'move_threads_to': '',

+ 23 - 16
misago/categories/tests/test_permissions_admin_views.py

@@ -53,14 +53,16 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
         test_role = CategoryRole.objects.get(name='Test CategoryRole')
         test_role = CategoryRole.objects.get(name='Test CategoryRole')
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:permissions:categories:edit',
-                    kwargs={'role_id': test_role.pk}))
+            reverse('misago:admin:permissions:categories:edit', kwargs={
+                'pk': test_role.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test CategoryRole', response.content)
         self.assertIn('Test CategoryRole', response.content)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:permissions:categories:edit',
-                    kwargs={'role_id': test_role.pk}),
+            reverse('misago:admin:permissions:categories:edit', kwargs={
+                'pk': test_role.pk
+            }),
             data=fake_data({'name': 'Top Lel'}))
             data=fake_data({'name': 'Top Lel'}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
@@ -78,8 +80,9 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
 
 
         test_role = CategoryRole.objects.get(name='Test CategoryRole')
         test_role = CategoryRole.objects.get(name='Test CategoryRole')
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:permissions:categories:delete',
-                    kwargs={'role_id': test_role.pk}))
+            reverse('misago:admin:permissions:categories:delete', kwargs={
+                'pk': test_role.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:permissions:categories:index'))
         self.client.get(reverse('misago:admin:permissions:categories:index'))
@@ -142,7 +145,7 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
         # See if form page is rendered
         # See if form page is rendered
         response = self.client.get(
         response = self.client.get(
             reverse('misago:admin:categories:nodes:permissions',
             reverse('misago:admin:categories:nodes:permissions',
-                    kwargs={'category_id': test_category.pk}))
+                    kwargs={'pk': test_category.pk}))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(test_category.name, response.content)
         self.assertIn(test_category.name, response.content)
         self.assertIn(test_role_a.name, response.content)
         self.assertIn(test_role_a.name, response.content)
@@ -153,7 +156,7 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
         # Assign roles to categories
         # Assign roles to categories
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:categories:nodes:permissions',
             reverse('misago:admin:categories:nodes:permissions',
-                    kwargs={'category_id': test_category.pk}),
+                    kwargs={'pk': test_category.pk}),
             data={
             data={
                 ('%s-category_role' % test_role_a.pk): role_full.pk,
                 ('%s-category_role' % test_role_a.pk): role_full.pk,
                 ('%s-category_role' % test_role_b.pk): role_comments.pk,
                 ('%s-category_role' % test_role_b.pk): role_comments.pk,
@@ -183,8 +186,9 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
 
 
         self.assertEqual(Category.objects.count(), 2)
         self.assertEqual(Category.objects.count(), 2)
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:permissions:users:categories',
-                    kwargs={'role_id': test_role.pk}))
+            reverse('misago:admin:permissions:users:categories', kwargs={
+                'pk': test_role.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         """
         """
@@ -232,8 +236,9 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
 
 
         # See if form page is rendered
         # See if form page is rendered
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:permissions:users:categories',
-                    kwargs={'role_id': test_role.pk}))
+            reverse('misago:admin:permissions:users:categories', kwargs={
+                'pk': test_role.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(category_a.name, response.content)
         self.assertIn(category_a.name, response.content)
         self.assertIn(category_b.name, response.content)
         self.assertIn(category_b.name, response.content)
@@ -253,16 +258,18 @@ class CategoryRoleAdminViewsTests(AdminTestCase):
 
 
         # See if form contains those roles
         # See if form contains those roles
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:admin:permissions:users:categories',
-                    kwargs={'role_id': test_role.pk}))
+            reverse('misago:admin:permissions:users:categories', kwargs={
+                'pk': test_role.pk
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(role_comments.name, response.content)
         self.assertIn(role_comments.name, response.content)
         self.assertIn(role_full.name, response.content)
         self.assertIn(role_full.name, response.content)
 
 
         # Assign roles to categories
         # Assign roles to categories
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:permissions:users:categories',
-                    kwargs={'role_id': test_role.pk}),
+            reverse('misago:admin:permissions:users:categories', kwargs={
+                'pk': test_role.pk
+            }),
             data={
             data={
                 ('%s-role' % category_a.pk): role_comments.pk,
                 ('%s-role' % category_a.pk): role_comments.pk,
                 ('%s-role' % category_b.pk): role_comments.pk,
                 ('%s-role' % category_b.pk): role_comments.pk,

+ 7 - 5
misago/conf/admin.py

@@ -8,11 +8,13 @@ class MisagoAdminExtension(object):
 
 
         urlpatterns.patterns('settings',
         urlpatterns.patterns('settings',
             url(r'^$', 'misago.conf.views.index', name='index'),
             url(r'^$', 'misago.conf.views.index', name='index'),
-            url(r'^(?P<group_key>(\w|-)+)/$', 'misago.conf.views.group', name='group'),
+            url(r'^(?P<key>(\w|-)+)/$', 'misago.conf.views.group', name='group'),
         )
         )
 
 
     def register_navigation_nodes(self, site):
     def register_navigation_nodes(self, site):
-        site.add_node(name=_("Settings"),
-                      icon='fa fa-gears',
-                      parent='misago:admin',
-                      link='misago:admin:settings:index')
+        site.add_node(
+            name=_("Settings"),
+            icon='fa fa-gears',
+            parent='misago:admin',
+            link='misago:admin:settings:index',
+        )

+ 6 - 4
misago/conf/tests/test_admin_views.py

@@ -18,8 +18,9 @@ class AdminSettingsViewsTests(AdminTestCase):
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         for group in SettingsGroup.objects.all():
         for group in SettingsGroup.objects.all():
-            group_link = reverse('misago:admin:settings:group',
-                                 kwargs={'group_key': group.key})
+            group_link = reverse('misago:admin:settings:group', kwargs={
+                'key': group.key
+            })
             self.assertIn(group.name, response.content)
             self.assertIn(group.name, response.content)
             self.assertIn(group_link, response.content)
             self.assertIn(group_link, response.content)
 
 
@@ -28,8 +29,9 @@ class AdminSettingsViewsTests(AdminTestCase):
         each settings group view returns 200 and contains all settings in group
         each settings group view returns 200 and contains all settings in group
         """
         """
         for group in SettingsGroup.objects.all():
         for group in SettingsGroup.objects.all():
-            group_link = reverse('misago:admin:settings:group',
-                                 kwargs={'group_key': group.key})
+            group_link = reverse('misago:admin:settings:group', kwargs={
+                'key': group.key
+            })
             response = self.client.get(group_link)
             response = self.client.get(group_link)
 
 
             self.assertEqual(response.status_code, 200)
             self.assertEqual(response.status_code, 200)

+ 3 - 3
misago/conf/views.py

@@ -24,9 +24,9 @@ def index(request):
     return render(request, 'misago/admin/conf/index.html')
     return render(request, 'misago/admin/conf/index.html')
 
 
 
 
-def group(request, group_key):
+def group(request, key):
     try:
     try:
-        active_group = SettingsGroup.objects.get(key=group_key)
+        active_group = SettingsGroup.objects.get(key=key)
     except SettingsGroup.DoesNotExist:
     except SettingsGroup.DoesNotExist:
         messages.error(request, _("Settings group could not be found."))
         messages.error(request, _("Settings group could not be found."))
         return redirect('misago:admin:settings:index')
         return redirect('misago:admin:settings:index')
@@ -49,7 +49,7 @@ def group(request, group_key):
 
 
             messages.success(
             messages.success(
                 request, _('Changes in settings have been saved!'))
                 request, _('Changes in settings have been saved!'))
-            return redirect('misago:admin:settings:group', group_key=group_key)
+            return redirect('misago:admin:settings:group', key=key)
 
 
     use_single_form_template = (len(fieldsets) == 1 and
     use_single_form_template = (len(fieldsets) == 1 and
                                 not fieldsets[0]['legend'])
                                 not fieldsets[0]['legend'])

+ 1 - 1
misago/core/exceptionhandler.py

@@ -49,7 +49,7 @@ def handle_outdated_slug_exception(request, exception):
     model = exception.args[0]
     model = exception.args[0]
     model_name = model.__class__.__name__.lower()
     model_name = model.__class__.__name__.lower()
     url_kwargs = request.resolver_match.kwargs
     url_kwargs = request.resolver_match.kwargs
-    url_kwargs['%s_slug' % model_name] = model.slug
+    url_kwargs['slug'] = model.slug
 
 
     new_url = reverse(view_name, kwargs=url_kwargs)
     new_url = reverse(view_name, kwargs=url_kwargs)
     return HttpResponsePermanentRedirect(new_url)
     return HttpResponsePermanentRedirect(new_url)

+ 1 - 1
misago/core/templatetags/misago_capture.py

@@ -3,7 +3,7 @@ Capture tag: renders its contents as template, and stores them in value
 
 
 Syntax:
 Syntax:
 {% capture trimmed as loremipsum %}
 {% capture trimmed as loremipsum %}
-<a href="{% url 'misago:terms_of_service' %}">{% trans "guidelines" %}</a>
+<a href="{% url 'misago:terms-of-service' %}">{% trans "guidelines" %}</a>
 {% endcapture %} # renders block contents to context variable loremipsum
 {% endcapture %} # renders block contents to context variable loremipsum
 """
 """
 
 

+ 13 - 13
misago/core/testproject/urls.py

@@ -6,17 +6,17 @@ urlpatterns = patterns('',
 )
 )
 
 
 urlpatterns += patterns('misago.core.testproject.views',
 urlpatterns += patterns('misago.core.testproject.views',
-    url(r'^forum/test-mail-user/$', 'test_mail_user', name='test_mail_user'),
-    url(r'^forum/test-mail-users/$', 'test_mail_users', name='test_mail_users'),
-    url(r'^forum/test-pagination/$', 'test_pagination', name='test_pagination'),
-    url(r'^forum/test-pagination/(?P<page>[1-9][0-9]*)/$', 'test_pagination', name='test_pagination'),
-    url(r'^forum/test-valid-slug/(?P<model_slug>[a-z0-9\-]+)-(?P<model_id>\d+)/$', 'validate_slug_view', name='validate_slug_view'),
-    url(r'^forum/test-banned/$', 'raise_misago_banned', name='raise_misago_banned'),
-    url(r'^forum/test-403/$', 'raise_misago_403', name='raise_misago_403'),
-    url(r'^forum/test-404/$', 'raise_misago_404', name='raise_misago_404'),
-    url(r'^forum/test-405/$', 'raise_misago_405', name='raise_misago_405'),
-    url(r'^test-403/$', 'raise_403', name='raise_403'),
-    url(r'^test-404/$', 'raise_404', name='raise_404'),
-    url(r'^test-redirect/$', 'test_redirect', name='test_redirect'),
-    url(r'^test-require-post/$', 'test_require_post', name='test_require_post'),
+    url(r'^forum/test-mail-user/$', 'test_mail_user', name='test-mail-user'),
+    url(r'^forum/test-mail-users/$', 'test_mail_users', name='test-mail-users'),
+    url(r'^forum/test-pagination/$', 'test_pagination', name='test-pagination'),
+    url(r'^forum/test-pagination/(?P<page>[1-9][0-9]*)/$', 'test_pagination', name='test-pagination'),
+    url(r'^forum/test-valid-slug/(?P<slug>[a-z0-9\-]+)-(?P<pk>\d+)/$', 'validate_slug_view', name='validate-slug-view'),
+    url(r'^forum/test-banned/$', 'raise_misago_banned', name='raise-misago-banned'),
+    url(r'^forum/test-403/$', 'raise_misago_403', name='raise-misago-403'),
+    url(r'^forum/test-404/$', 'raise_misago_404', name='raise-misago-404'),
+    url(r'^forum/test-405/$', 'raise_misago_405', name='raise-misago-405'),
+    url(r'^test-403/$', 'raise_403', name='raise-403'),
+    url(r'^test-404/$', 'raise_404', name='raise-404'),
+    url(r'^test-redirect/$', 'test_redirect', name='test-redirect'),
+    url(r'^test-require-post/$', 'test_require_post', name='test-require-post'),
 )
 )

+ 3 - 3
misago/core/testproject/views.py

@@ -41,9 +41,9 @@ def test_pagination(request, page=None):
     return HttpResponse(",".join([str(x) for x in page.object_list]))
     return HttpResponse(",".join([str(x) for x in page.object_list]))
 
 
 
 
-def validate_slug_view(request, model_id, model_slug):
-    model = Model(int(model_id), 'eric-the-fish')
-    validate_slug(model, model_slug)
+def validate_slug_view(request, pk, slug):
+    model = Model(int(pk), 'eric-the-fish')
+    validate_slug(model, slug)
     return HttpResponse("Allright!")
     return HttpResponse("Allright!")
 
 
 
 

+ 2 - 2
misago/core/tests/test_decorators.py

@@ -8,12 +8,12 @@ class RequirePostTests(TestCase):
 
 
     def test_require_POST_success(self):
     def test_require_POST_success(self):
         """require_POST decorator allowed POST request"""
         """require_POST decorator allowed POST request"""
-        response = self.client.post(reverse('test_require_post'))
+        response = self.client.post(reverse('test-require-post'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.content, 'Request method: POST')
         self.assertEqual(response.content, 'Request method: POST')
 
 
     def test_require_POST_fail_GET(self):
     def test_require_POST_fail_GET(self):
         """require_POST decorator failed on GET request"""
         """require_POST decorator failed on GET request"""
-        response = self.client.get(reverse('test_require_post'))
+        response = self.client.get(reverse('test-require-post'))
         self.assertEqual(response.status_code, 405)
         self.assertEqual(response.status_code, 405)
         self.assertIn("Wrong way", response.content)
         self.assertIn("Wrong way", response.content)

+ 9 - 9
misago/core/tests/test_errorpages.py

@@ -23,25 +23,25 @@ class ErrorPageViewsTests(TestCase):
 
 
     def test_banned_returns_403(self):
     def test_banned_returns_403(self):
         """banned error page has no show-stoppers"""
         """banned error page has no show-stoppers"""
-        response = self.client.get(reverse('raise_misago_banned'))
+        response = self.client.get(reverse('raise-misago-banned'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn("<p>Banned for test!</p>", response.content)
         self.assertIn("<p>Banned for test!</p>", response.content)
 
 
     def test_permission_denied_returns_403(self):
     def test_permission_denied_returns_403(self):
         """permission_denied error page has no show-stoppers"""
         """permission_denied error page has no show-stoppers"""
-        response = self.client.get(reverse('raise_misago_403'))
+        response = self.client.get(reverse('raise-misago-403'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn("Page not available", response.content)
         self.assertIn("Page not available", response.content)
 
 
     def test_page_not_found_returns_404(self):
     def test_page_not_found_returns_404(self):
         """page_not_found error page has no show-stoppers"""
         """page_not_found error page has no show-stoppers"""
-        response = self.client.get(reverse('raise_misago_404'))
+        response = self.client.get(reverse('raise-misago-404'))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
         self.assertIn("Page not found", response.content)
         self.assertIn("Page not found", response.content)
 
 
     def test_not_allowed_returns_405(self):
     def test_not_allowed_returns_405(self):
         """not allowed error page has no showstoppers"""
         """not allowed error page has no showstoppers"""
-        response = self.client.get(reverse('raise_misago_405'))
+        response = self.client.get(reverse('raise-misago-405'))
         self.assertEqual(response.status_code, 405)
         self.assertEqual(response.status_code, 405)
         self.assertIn("Wrong way", response.content)
         self.assertIn("Wrong way", response.content)
 
 
@@ -51,7 +51,7 @@ class CustomErrorPagesTests(TestCase):
 
 
     def setUp(self):
     def setUp(self):
         self.misago_request = RequestFactory().get(reverse('misago:index'))
         self.misago_request = RequestFactory().get(reverse('misago:index'))
-        self.site_request = RequestFactory().get(reverse('raise_403'))
+        self.site_request = RequestFactory().get(reverse('raise-403'))
 
 
         self.misago_request.user = AnonymousUser()
         self.misago_request.user = AnonymousUser()
         self.site_request.user = AnonymousUser()
         self.site_request.user = AnonymousUser()
@@ -61,9 +61,9 @@ class CustomErrorPagesTests(TestCase):
 
 
     def test_shared_403_decorator(self):
     def test_shared_403_decorator(self):
         """shared_403_decorator calls correct error handler"""
         """shared_403_decorator calls correct error handler"""
-        response = self.client.get(reverse('raise_misago_403'))
+        response = self.client.get(reverse('raise-misago-403'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
-        response = self.client.get(reverse('raise_403'))
+        response = self.client.get(reverse('raise-403'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn("Custom 403", response.content)
         self.assertIn("Custom 403", response.content)
 
 
@@ -74,9 +74,9 @@ class CustomErrorPagesTests(TestCase):
 
 
     def test_shared_404_decorator(self):
     def test_shared_404_decorator(self):
         """shared_404_decorator calls correct error handler"""
         """shared_404_decorator calls correct error handler"""
-        response = self.client.get(reverse('raise_misago_404'))
+        response = self.client.get(reverse('raise-misago-404'))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
-        response = self.client.get(reverse('raise_404'))
+        response = self.client.get(reverse('raise-404'))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
         self.assertIn("Custom 404", response.content)
         self.assertIn("Custom 404", response.content)
 
 

+ 2 - 2
misago/core/tests/test_mailer.py

@@ -12,7 +12,7 @@ class MisagoMailerTests(TestCase):
         User = get_user_model()
         User = get_user_model()
         User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
         User.objects.create_user('Bob', 'bob@bob.com', 'pass123')
 
 
-        response = self.client.get(reverse('test_mail_user'))
+        response = self.client.get(reverse('test-mail-user'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         self.assertEqual(mail.outbox[0].subject, "Misago Test Mail")
         self.assertEqual(mail.outbox[0].subject, "Misago Test Mail")
@@ -28,7 +28,7 @@ class MisagoMailerTests(TestCase):
             User.objects.create_user('Uniform', 'uniform@test.com', 'pass123'),
             User.objects.create_user('Uniform', 'uniform@test.com', 'pass123'),
         )
         )
 
 
-        response = self.client.get(reverse('test_mail_users'))
+        response = self.client.get(reverse('test-mail-users'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         spams_sent = 0
         spams_sent = 0

+ 6 - 6
misago/core/tests/test_page.py

@@ -9,18 +9,18 @@ class SiteTests(TestCase):
     def test_pages(self):
     def test_pages(self):
         """add_section adds section to page"""
         """add_section adds section to page"""
         self.page.add_section(
         self.page.add_section(
-            link='misago:user_posts',
+            link='misago:user-posts',
             name='Posts',
             name='Posts',
-            after='misago:user_threads')
+            after='misago:user-threads')
 
 
         self.page.add_section(
         self.page.add_section(
-            link='misago:user_threads',
+            link='misago:user-threads',
             name='Threads')
             name='Threads')
 
 
         self.page.add_section(
         self.page.add_section(
-            link='misago:user_follows',
+            link='misago:user-follows',
             name='Follows',
             name='Follows',
-            before='misago:user_posts')
+            before='misago:user-posts')
 
 
         self.page.assert_is_finalized()
         self.page.assert_is_finalized()
 
 
@@ -29,4 +29,4 @@ class SiteTests(TestCase):
         self.assertEqual(sorted_sections[1]['name'], 'Follows')
         self.assertEqual(sorted_sections[1]['name'], 'Follows')
         self.assertEqual(sorted_sections[2]['name'], 'Posts')
         self.assertEqual(sorted_sections[2]['name'], 'Posts')
 
 
-        self.assertEqual(self.page.get_default_link(), 'misago:user_threads')
+        self.assertEqual(self.page.get_default_link(), 'misago:user-threads')

+ 12 - 10
misago/core/tests/test_shortcuts.py

@@ -11,25 +11,25 @@ class PaginateTests(TestCase):
     def test_valid_page_handling(self):
     def test_valid_page_handling(self):
         """Valid page number causes no errors"""
         """Valid page number causes no errors"""
         response = self.client.get(
         response = self.client.get(
-            reverse('test_pagination', kwargs={'page': 2}))
+            reverse('test-pagination', kwargs={'page': 2}))
         self.assertEqual("5,6,7,8,9", response.content)
         self.assertEqual("5,6,7,8,9", response.content)
 
 
     def test_invalid_page_handling(self):
     def test_invalid_page_handling(self):
         """Invalid page number results in 404 error"""
         """Invalid page number results in 404 error"""
         response = self.client.get(
         response = self.client.get(
-            reverse('test_pagination', kwargs={'page': 42}))
+            reverse('test-pagination', kwargs={'page': 42}))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
     def test_implicit_page_handling(self):
     def test_implicit_page_handling(self):
         """Implicit page number causes no errors"""
         """Implicit page number causes no errors"""
         response = self.client.get(
         response = self.client.get(
-            reverse('test_pagination'))
+            reverse('test-pagination'))
         self.assertEqual("0,1,2,3,4", response.content)
         self.assertEqual("0,1,2,3,4", response.content)
 
 
     def test_explicit_page_handling(self):
     def test_explicit_page_handling(self):
         """Explicit page number results in redirect"""
         """Explicit page number results in redirect"""
         response = self.client.get(
         response = self.client.get(
-            reverse('test_pagination', kwargs={'page': 1}))
+            reverse('test-pagination', kwargs={'page': 1}))
         valid_url = "http://testserver/forum/test-pagination/"
         valid_url = "http://testserver/forum/test-pagination/"
         self.assertEqual(response['Location'], valid_url)
         self.assertEqual(response['Location'], valid_url)
 
 
@@ -39,16 +39,18 @@ class ValidateSlugTests(TestCase):
 
 
     def test_valid_slug_handling(self):
     def test_valid_slug_handling(self):
         """Valid slug causes no interruption in view processing"""
         """Valid slug causes no interruption in view processing"""
-        test_kwargs = {'model_slug': 'eric-the-fish', 'model_id': 1}
-        response = self.client.get(
-            reverse('validate_slug_view', kwargs=test_kwargs))
+        response = self.client.get(reverse('validate-slug-view', kwargs={
+            'slug': 'eric-the-fish',
+            'pk': 1,
+        }))
         self.assertIn("Allright", response.content)
         self.assertIn("Allright", response.content)
 
 
     def test_invalid_slug_handling(self):
     def test_invalid_slug_handling(self):
         """Invalid slug returns in redirect to valid page"""
         """Invalid slug returns in redirect to valid page"""
-        test_kwargs = {'model_slug': 'lion-the-eric', 'model_id': 1}
-        response = self.client.get(
-            reverse('validate_slug_view', kwargs=test_kwargs))
+        response = self.client.get(reverse('validate-slug-view', kwargs={
+            'slug': 'lion-the-eric',
+            'pk': 1,
+        }))
 
 
         valid_url = "http://testserver/forum/test-valid-slug/eric-the-fish-1/"
         valid_url = "http://testserver/forum/test-valid-slug/eric-the-fish-1/"
         self.assertEqual(response['Location'], valid_url)
         self.assertEqual(response['Location'], valid_url)

+ 1 - 1
misago/core/tests/test_templatetags.py

@@ -175,7 +175,7 @@ class PaginationTests(TestCase):
         tpl_content = """
         tpl_content = """
 {% load misago_pagination %}
 {% load misago_pagination %}
 
 
-{% pagination page "misago/user/pagination.html" 'misago:user_warnings' user_slug=user.slug user_id=user.pk %}
+{% pagination page "misago/user/pagination.html" 'misago:user_warnings' slug=user.slug pk=user.pk %}
 """
 """
 
 
         tpl = Template(tpl_content)
         tpl = Template(tpl_content)

+ 1 - 1
misago/core/tests/test_views.py

@@ -28,7 +28,7 @@ class RedirectViewTests(TestCase):
 
 
     def test_redirect_view(self):
     def test_redirect_view(self):
         """redirect view always redirects to home page"""
         """redirect view always redirects to home page"""
-        response = self.client.get(reverse('test_redirect'))
+        response = self.client.get(reverse('test-redirect'))
 
 
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
         self.assertTrue(response['location'].endswith(reverse('misago:index')))
         self.assertTrue(response['location'].endswith(reverse('misago:index')))

+ 2 - 2
misago/legal/context_processors.py

@@ -9,12 +9,12 @@ def legal_links(request):
         legal_context['TERMS_OF_SERVICE_URL'] = settings.terms_of_service_link
         legal_context['TERMS_OF_SERVICE_URL'] = settings.terms_of_service_link
     elif settings.terms_of_service:
     elif settings.terms_of_service:
         legal_context['TERMS_OF_SERVICE_URL'] = reverse(
         legal_context['TERMS_OF_SERVICE_URL'] = reverse(
-            'misago:terms_of_service')
+            'misago:terms-of-service')
 
 
     if settings.privacy_policy_link:
     if settings.privacy_policy_link:
         legal_context['PRIVACY_POLICY_URL'] = settings.privacy_policy_link
         legal_context['PRIVACY_POLICY_URL'] = settings.privacy_policy_link
     elif settings.privacy_policy:
     elif settings.privacy_policy:
-        legal_context['PRIVACY_POLICY_URL'] = reverse('misago:privacy_policy')
+        legal_context['PRIVACY_POLICY_URL'] = reverse('misago:privacy-policy')
 
 
     if legal_context:
     if legal_context:
         request.frontend_context.update(legal_context)
         request.frontend_context.update(legal_context)

+ 8 - 8
misago/legal/tests.py

@@ -21,7 +21,7 @@ class TermsOfServiceTests(TestCase):
         self.assertFalse(settings.terms_of_service_link)
         self.assertFalse(settings.terms_of_service_link)
         self.assertFalse(settings.terms_of_service)
         self.assertFalse(settings.terms_of_service)
 
 
-        response = self.client.get(reverse('misago:terms_of_service'))
+        response = self.client.get(reverse('misago:terms-of-service'))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
     def test_301_on_link_tos(self):
     def test_301_on_link_tos(self):
@@ -31,7 +31,7 @@ class TermsOfServiceTests(TestCase):
         self.assertTrue(settings.terms_of_service_link)
         self.assertTrue(settings.terms_of_service_link)
         self.assertTrue(settings.terms_of_service)
         self.assertTrue(settings.terms_of_service)
 
 
-        response = self.client.get(reverse('misago:terms_of_service'))
+        response = self.client.get(reverse('misago:terms-of-service'))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response['location'], 'http://test.com')
         self.assertEqual(response['location'], 'http://test.com')
 
 
@@ -42,7 +42,7 @@ class TermsOfServiceTests(TestCase):
         self.assertTrue(settings.terms_of_service_title)
         self.assertTrue(settings.terms_of_service_title)
         self.assertTrue(settings.terms_of_service)
         self.assertTrue(settings.terms_of_service)
 
 
-        response = self.client.get(reverse('misago:terms_of_service'))
+        response = self.client.get(reverse('misago:terms-of-service'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test ToS', response.content)
         self.assertIn('Test ToS', response.content)
         self.assertIn('Lorem ipsum dolor', response.content)
         self.assertIn('Lorem ipsum dolor', response.content)
@@ -58,7 +58,7 @@ class TermsOfServiceTests(TestCase):
         context_dict = legal_links(MockRequest())
         context_dict = legal_links(MockRequest())
 
 
         self.assertEqual(context_dict, {
         self.assertEqual(context_dict, {
-            'TERMS_OF_SERVICE_URL': reverse('misago:terms_of_service')
+            'TERMS_OF_SERVICE_URL': reverse('misago:terms-of-service')
         })
         })
 
 
     def test_context_processor_remote_tos(self):
     def test_context_processor_remote_tos(self):
@@ -88,7 +88,7 @@ class PrivacyPolicyTests(TestCase):
         self.assertFalse(settings.privacy_policy_link)
         self.assertFalse(settings.privacy_policy_link)
         self.assertFalse(settings.privacy_policy)
         self.assertFalse(settings.privacy_policy)
 
 
-        response = self.client.get(reverse('misago:privacy_policy'))
+        response = self.client.get(reverse('misago:privacy-policy'))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
     def test_301_on_link_policy(self):
     def test_301_on_link_policy(self):
@@ -98,7 +98,7 @@ class PrivacyPolicyTests(TestCase):
         self.assertTrue(settings.privacy_policy_link)
         self.assertTrue(settings.privacy_policy_link)
         self.assertTrue(settings.privacy_policy)
         self.assertTrue(settings.privacy_policy)
 
 
-        response = self.client.get(reverse('misago:privacy_policy'))
+        response = self.client.get(reverse('misago:privacy-policy'))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response['location'], 'http://test.com')
         self.assertEqual(response['location'], 'http://test.com')
 
 
@@ -109,7 +109,7 @@ class PrivacyPolicyTests(TestCase):
         self.assertTrue(settings.privacy_policy_title)
         self.assertTrue(settings.privacy_policy_title)
         self.assertTrue(settings.privacy_policy)
         self.assertTrue(settings.privacy_policy)
 
 
-        response = self.client.get(reverse('misago:privacy_policy'))
+        response = self.client.get(reverse('misago:privacy-policy'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Test Policy', response.content)
         self.assertIn('Test Policy', response.content)
         self.assertIn('Lorem ipsum dolor', response.content)
         self.assertIn('Lorem ipsum dolor', response.content)
@@ -125,7 +125,7 @@ class PrivacyPolicyTests(TestCase):
         context_dict = legal_links(MockRequest())
         context_dict = legal_links(MockRequest())
 
 
         self.assertEqual(context_dict, {
         self.assertEqual(context_dict, {
-            'PRIVACY_POLICY_URL': reverse('misago:privacy_policy')
+            'PRIVACY_POLICY_URL': reverse('misago:privacy-policy')
         })
         })
 
 
     def test_context_processor_remote_policy(self):
     def test_context_processor_remote_policy(self):

+ 2 - 2
misago/legal/urls.py

@@ -2,6 +2,6 @@ from django.conf.urls import patterns, url
 
 
 
 
 urlpatterns = patterns('misago.legal.views',
 urlpatterns = patterns('misago.legal.views',
-    url(r'^terms-of-service/$', 'terms_of_service', name='terms_of_service'),
-    url(r'^privacy-policy/$', 'privacy_policy', name='privacy_policy'),
+    url(r'^terms-of-service/$', 'terms_of_service', name='terms-of-service'),
+    url(r'^privacy-policy/$', 'privacy_policy', name='privacy-policy'),
 )
 )

+ 1 - 1
misago/templates/misago/activation/error.html

@@ -18,7 +18,7 @@
         <p class="lead">{% trans "Can't activate account." %}</p>
         <p class="lead">{% trans "Can't activate account." %}</p>
         <p>{{ message }}</p>
         <p>{{ message }}</p>
         <p>
         <p>
-          <a href="{% url 'misago:request_activation' %}">
+          <a href="{% url 'misago:request-activation' %}">
             Request another activation link.
             Request another activation link.
           </a>
           </a>
         </p>
         </p>

+ 3 - 3
misago/templates/misago/admin/bans/list.html

@@ -40,18 +40,18 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link ban_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:users:bans:edit' ban_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:users:bans:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <form action="{% url 'misago:admin:users:bans:delete' ban_id=item.id %}" method="post" class="delete-prompt">
+  <form action="{% url 'misago:admin:users:bans:delete' pk=item.pk %}" method="post" class="delete-prompt">
     <button class="btn btn-danger tooltip-top" title="{% trans "Remove" %}">
     <button class="btn btn-danger tooltip-top" title="{% trans "Remove" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-times"></span>
       <span class="fa fa-times"></span>

+ 5 - 5
misago/templates/misago/admin/categories/list.html

@@ -33,7 +33,7 @@
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not item.last %}
   {% if not item.last %}
-  <form action="{% url 'misago:admin:categories:nodes:down' category_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:categories:nodes:down' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-down"></span>
       <span class="fa fa-chevron-down"></span>
@@ -45,7 +45,7 @@
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not item.first %}
   {% if not item.first %}
-  <form action="{% url 'misago:admin:categories:nodes:up' category_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:categories:nodes:up' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-up"></span>
       <span class="fa fa-chevron-up"></span>
@@ -57,18 +57,18 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link category_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:categories:nodes:edit' category_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:categories:nodes:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:categories:nodes:delete' category_id=item.id %}" class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
+  <a href="{% url 'misago:admin:categories:nodes:delete' pk=item.pk %}" class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
     <span class="fa fa-times"></span>
     <span class="fa fa-times"></span>
   </a>
   </a>
 </td>
 </td>

+ 2 - 2
misago/templates/misago/admin/categoryroles/list.html

@@ -24,12 +24,12 @@
   {{ item }}
   {{ item }}
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:permissions:categories:edit' role_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:permissions:categories:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <form action="{% url 'misago:admin:permissions:categories:delete' role_id=item.id %}" method="post" class="delete-prompt">
+  <form action="{% url 'misago:admin:permissions:categories:delete' pk=item.pk %}" method="post" class="delete-prompt">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-times"></span>
       <span class="fa fa-times"></span>

+ 2 - 2
misago/templates/misago/admin/conf/index.html

@@ -24,7 +24,7 @@
       <ul class="nav nav-side">
       <ul class="nav nav-side">
         {% for group in settings_groups %}
         {% for group in settings_groups %}
         <li {% if group.key == active_group.key %}class="active"{% endif %}>
         <li {% if group.key == active_group.key %}class="active"{% endif %}>
-          <a href="{% url 'misago:admin:settings:group' group_key=group.key %}">
+          <a href="{% url 'misago:admin:settings:group' key=group.key %}">
             {{ group.name }}
             {{ group.name }}
           </a>
           </a>
         </li>
         </li>
@@ -39,7 +39,7 @@
         <div class="list-group">
         <div class="list-group">
 
 
           {% for group in settings_groups %}
           {% for group in settings_groups %}
-          <a href="{% url 'misago:admin:settings:group' group_key=group.key %}" class="list-group-item">
+          <a href="{% url 'misago:admin:settings:group' key=group.key %}" class="list-group-item">
             <h4 class="list-group-item-heading">{{ group.name }}</h4>
             <h4 class="list-group-item-heading">{{ group.name }}</h4>
             {% if group.description %}
             {% if group.description %}
             <p class="list-group-item-text">{{ group.description }}</p>
             <p class="list-group-item-text">{{ group.description }}</p>

+ 1 - 1
misago/templates/misago/admin/index.html

@@ -115,7 +115,7 @@
       $button.find('.fa').attr("class", "fa fa-refresh fa-fw fa-spin");
       $button.find('.fa').attr("class", "fa fa-refresh fa-fw fa-spin");
       $button.find('.name').text("{% trans "Checking..." %}");
       $button.find('.name').text("{% trans "Checking..." %}");
 
 
-      $.post("{% url 'misago:admin:check_version' %}", $form.serialize(), function(data) {
+      $.post("{% url 'misago:admin:check-version' %}", $form.serialize(), function(data) {
         if (data.is_error) {
         if (data.is_error) {
           var $message = $('<p class="lead text-danger"><span class="fa fa-times fa-lg fa-fw"></span></p>');
           var $message = $('<p class="lead text-danger"><span class="fa fa-times fa-lg fa-fw"></span></p>');
         } else {
         } else {

+ 0 - 62
misago/templates/misago/admin/labels/form.html

@@ -1,62 +0,0 @@
-{% extends "misago/admin/generic/form.html" %}
-{% load i18n misago_forms %}
-
-
-{% block title %}
-{% if target.pk %}
-{{ target }}
-{% else %}
-{% trans "New label" %}
-{% endif %} | {{ active_link.name }} | {{ block.super }}
-{% endblock title %}
-
-
-{% block page-target %}
-{% if target.pk %}
-{{ target }}
-{% else %}
-{% trans "New label" %}
-{% endif %}
-{% endblock page-target %}
-
-
-{% block form-header %}
-<h1>
-  {% if target.pk %}
-  {{ target }}
-  {% else %}
-  {% trans "New label" %}
-  {% endif %}
-</h1>
-{% endblock %}
-
-
-{% block form-extra %}
-class="form-horizontal"
-{% endblock form-extra%}
-
-
-{% block form-body %}
-<div class="form-body">
-  {% with label_class="col-md-3" field_class="col-md-9" %}
-  <fieldset>
-    <legend>{% trans "Name and appearance" %}</legend>
-
-    {% form_row form.name label_class field_class %}
-    {% form_row form.css_class label_class field_class %}
-
-  </fieldset>
-  <fieldset>
-    <legend>{% trans "Availability" %}</legend>
-
-    {% form_row form.forums label_class field_class %}
-
-  </fieldset>
-  {% endwith %}
-</div>
-{% endblock form-body %}
-
-
-{% block form-footer-class %}
-col-md-offset-3
-{% endblock form-footer-class %}

+ 0 - 70
misago/templates/misago/admin/labels/list.html

@@ -1,70 +0,0 @@
-{% extends "misago/admin/generic/list.html" %}
-{% load i18n %}
-
-
-{% block page-actions %}
-<div class="page-actions">
-  <a href="{% url 'misago:admin:forums:labels:new' %}" class="btn btn-success">
-    <span class="fa fa-plus-circle"></span>
-    {% trans "New label" %}
-  </a>
-</div>
-{% endblock %}
-
-
-{% block table-header %}
-<th>{% trans "Label" %}</th>
-<th style="width: 40%;">{% trans "CSS class" %}</th>
-{% for action in extra_actions %}
-<th style="width: 1%;">&nbsp;</th>
-{% endfor %}
-<th style="width: 1%;">&nbsp;</th>
-<th style="width: 1%;">&nbsp;</th>
-{% endblock table-header %}
-
-
-{% block table-row %}
-<td class="item-name">
-  {{ item }}
-</td>
-<td>{% if item.css_class %}{{ item.css_class }}{% else %}&nbsp;{% endif %}</td>
-{% for action in extra_actions %}
-<td class="row-action">
-  <a href="{% url action.link label_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
-    <span class="{{ action.icon }}"></span>
-  </a>
-</td>
-{% endfor %}
-<td class="row-action">
-  <a href="{% url 'misago:admin:forums:labels:edit' label_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
-    <span class="fa fa-pencil"></span>
-  </a>
-</td>
-<td class="row-action">
-  <form action="{% url 'misago:admin:forums:labels:delete' label_id=item.id %}" method="post" class="delete-prompt">
-    <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
-      {% csrf_token %}
-      <span class="fa fa-times"></span>
-    </button>
-  </form>
-</td>
-{% endblock %}
-
-
-{% block emptylist %}
-<td colspan="{{ 4|add:extra_actions_len }}">
-  <p>{% trans "No thread labels are currently defined." %}</p>
-</td>
-{% endblock emptylist %}
-
-
-{% block javascripts %}
-<script type="text/javascript">
-  $(function() {
-    $('.delete-prompt').submit(function() {
-      var decision = confirm("{% trans "Are you sure you want to delete this label?" %}");
-      return decision;
-    });
-  });
-</script>
-{% endblock %}

+ 1 - 1
misago/templates/misago/admin/navbar.html

@@ -15,7 +15,7 @@
       </ul>
       </ul>
       <div class="user-nav pull-right">
       <div class="user-nav pull-right">
         <p class="navbar-text">
         <p class="navbar-text">
-          <a href="{% url 'misago:admin:users:accounts:edit' user_id=user.id %}" class="tooltip-bottom" title="{% trans "Edit your account" %}">
+          <a href="{% url 'misago:admin:users:accounts:edit' pk=user.pk %}" class="tooltip-bottom" title="{% trans "Edit your account" %}">
             <img src="{{ user|avatar:30 }}" alt="{% trans "Your avatar" %}">
             <img src="{{ user|avatar:30 }}" alt="{% trans "Your avatar" %}">
             {{ user }}
             {{ user }}
           </a>
           </a>

+ 7 - 7
misago/templates/misago/admin/ranks/list.html

@@ -49,19 +49,19 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link rank_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:users:ranks:users' rank_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Users with rank" %}">
+  <a href="{% url 'misago:admin:users:ranks:users' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Users with rank" %}">
     <span class="fa fa-users"></span>
     <span class="fa fa-users"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not item.is_default %}
   {% if not item.is_default %}
-  <form action="{% url 'misago:admin:users:ranks:default' rank_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:users:ranks:default' pk=item.pk %}" method="post">
     <button class="btn btn-warning tooltip-top" title="{% trans "Make default" %}">
     <button class="btn btn-warning tooltip-top" title="{% trans "Make default" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-star"></span>
       <span class="fa fa-star"></span>
@@ -73,7 +73,7 @@
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not forloop.last %}
   {% if not forloop.last %}
-  <form action="{% url 'misago:admin:users:ranks:down' rank_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:users:ranks:down' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-down"></span>
       <span class="fa fa-chevron-down"></span>
@@ -85,7 +85,7 @@
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not forloop.first %}
   {% if not forloop.first %}
-  <form action="{% url 'misago:admin:users:ranks:up' rank_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:users:ranks:up' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-up"></span>
       <span class="fa fa-chevron-up"></span>
@@ -96,12 +96,12 @@
   {% endif %}
   {% endif %}
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:users:ranks:edit' rank_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:users:ranks:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <form action="{% url 'misago:admin:users:ranks:delete' rank_id=item.id %}" method="post" class="delete-prompt">
+  <form action="{% url 'misago:admin:users:ranks:delete' pk=item.pk %}" method="post" class="delete-prompt">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-times"></span>
       <span class="fa fa-times"></span>

+ 4 - 4
misago/templates/misago/admin/roles/list.html

@@ -29,23 +29,23 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link role_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:permissions:users:users' role_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Users with role" %}">
+  <a href="{% url 'misago:admin:permissions:users:users' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Users with role" %}">
     <span class="fa fa-users"></span>
     <span class="fa fa-users"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:permissions:users:edit' role_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:permissions:users:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <form action="{% url 'misago:admin:permissions:users:delete' role_id=item.id %}" method="post" class="delete-prompt">
+  <form action="{% url 'misago:admin:permissions:users:delete' pk=item.pk %}" method="post" class="delete-prompt">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-times"></span>
       <span class="fa fa-times"></span>

+ 3 - 3
misago/templates/misago/admin/users/delete.html

@@ -27,15 +27,15 @@
 
 
     <div class="extra-padding">
     <div class="extra-padding">
       <ul class="list-unstyled">
       <ul class="list-unstyled">
-        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete_threads' user_id=user.id %}" data-total="{{ user.thread_set.count }}">
+        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete-threads' pk=user.pk %}" data-total="{{ user.thread_set.count }}">
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           {% trans "Threads" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
           {% trans "Threads" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
         </li>
         </li>
-        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete_posts' user_id=user.id %}" data-total="{{ user.post_set.count }}">
+        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete-posts' pk=user.pk %}" data-total="{{ user.post_set.count }}">
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           {% trans "Posts" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
           {% trans "Posts" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
         </li>
         </li>
-        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete_account' user_id=user.id %}">
+        <li class="step queued" data-url="{% url 'misago:admin:users:accounts:delete-account' pk=user.pk %}">
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           <span class="fa fa-clock-o fa-fw text-muted"></span>
           {% trans "Account" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
           {% trans "Account" %}: <strong><em class="text-muted">{% trans "queued" %}</em></strong>
         </li>
         </li>

+ 2 - 2
misago/templates/misago/admin/users/list.html

@@ -69,13 +69,13 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link user_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:users:accounts:edit' user_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit user" %}">
+  <a href="{% url 'misago:admin:users:accounts:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit user" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>

+ 5 - 5
misago/templates/misago/admin/warnings/list.html

@@ -76,14 +76,14 @@
 </td>
 </td>
 {% for action in extra_actions %}
 {% for action in extra_actions %}
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url action.link rank_id=item.id %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
+  <a href="{% url action.link pk=item.pk %}" class="btn btn-{% if action.style %}{{ action.style }}{% else %}default{% endif %} tooltip-top" title="{{ action.name }}">
     <span class="{{ action.icon }}"></span>
     <span class="{{ action.icon }}"></span>
   </a>
   </a>
 </td>
 </td>
 {% endfor %}
 {% endfor %}
 <td class="row-action">
 <td class="row-action">
   {% if not forloop.last %}
   {% if not forloop.last %}
-  <form action="{% url 'misago:admin:users:warnings:down' warning_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:users:warnings:down' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move down" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-down"></span>
       <span class="fa fa-chevron-down"></span>
@@ -95,7 +95,7 @@
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
   {% if not forloop.first %}
   {% if not forloop.first %}
-  <form action="{% url 'misago:admin:users:warnings:up' warning_id=item.id %}" method="post">
+  <form action="{% url 'misago:admin:users:warnings:up' pk=item.pk %}" method="post">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
     <button class="btn btn-default tooltip-top" title="{% trans "Move up" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-chevron-up"></span>
       <span class="fa fa-chevron-up"></span>
@@ -106,12 +106,12 @@
   {% endif %}
   {% endif %}
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <a href="{% url 'misago:admin:users:warnings:edit' warning_id=item.id %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
+  <a href="{% url 'misago:admin:users:warnings:edit' pk=item.pk %}" class="btn btn-primary tooltip-top" title="{% trans "Edit" %}">
     <span class="fa fa-pencil"></span>
     <span class="fa fa-pencil"></span>
   </a>
   </a>
 </td>
 </td>
 <td class="row-action">
 <td class="row-action">
-  <form action="{% url 'misago:admin:users:warnings:delete' warning_id=item.id %}" method="post" class="delete-prompt">
+  <form action="{% url 'misago:admin:users:warnings:delete' pk=item.pk %}" method="post" class="delete-prompt">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
     <button class="btn btn-danger tooltip-top" title="{% trans "Delete" %}">
       {% csrf_token %}
       {% csrf_token %}
       <span class="fa fa-times"></span>
       <span class="fa fa-times"></span>

+ 1 - 1
misago/templates/misago/categories/last_activity.html

@@ -14,7 +14,7 @@
 
 
     {% capture trimmed as user %}
     {% capture trimmed as user %}
       {% if category.last_poster_id %}
       {% if category.last_poster_id %}
-        <a href="{% url 'misago:user' user_slug=category.last_poster_slug user_id=category.last_poster_id %}" class="poster-title">{{ category.last_poster_name }}</a>
+        <a href="{% url 'misago:user' slug=category.last_poster_slug id=category.last_poster_id %}" class="poster-title">{{ category.last_poster_name }}</a>
       {% else %}
       {% else %}
         <span class="poster-title">{{ category.last_poster_name }}</span>
         <span class="poster-title">{{ category.last_poster_name }}</span>
       {% endif %}
       {% endif %}

+ 1 - 1
misago/templates/misago/emails/activation/by_user.html

@@ -8,6 +8,6 @@
 {% endblocktrans %}
 {% endblocktrans %}
 <br>
 <br>
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.id token=activation_token %}">{% trans "Activate my account!" %}</a>
+<a href="{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
 <br>
 <br>
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/activation/by_user.txt

@@ -6,5 +6,5 @@
 {% blocktrans trimmed with user=recipient %}
 {% blocktrans trimmed with user=recipient %}
 {{ user }}, to activate your account click the below link:
 {{ user }}, to activate your account click the below link:
 {% endblocktrans %}
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.id token=activation_token %}
+{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_email.html

@@ -13,6 +13,6 @@ To confirm this change, click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
 <br>
 <br>
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:options_confirm_email_change' token=token %}">{% trans "Save changes" %}</a>
+<a href="{{ SITE_ADDRESS }}{% url 'misago:options-confirm-email-change' token=token %}">{% trans "Save changes" %}</a>
 <br>
 <br>
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_email.txt

@@ -10,5 +10,5 @@
 {% blocktrans trimmed %}
 {% blocktrans trimmed %}
 To confirm this change, click the link below:
 To confirm this change, click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:options_confirm_email_change' token=token %}
+{{ SITE_ADDRESS }}{% url 'misago:options-confirm-email-change' token=token %}
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_password.html

@@ -13,6 +13,6 @@ To confirm this change, click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
 <br>
 <br>
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:options_confirm_password_change' token=token %}">{% trans "Save changes" %}</a>
+<a href="{{ SITE_ADDRESS }}{% url 'misago:options-confirm-password-change' token=token %}">{% trans "Save changes" %}</a>
 <br>
 <br>
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_password.txt

@@ -10,5 +10,5 @@
 {% blocktrans trimmed %}
 {% blocktrans trimmed %}
 To confirm this change, click the link below:
 To confirm this change, click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:options_confirm_password_change' token=token %}
+{{ SITE_ADDRESS }}{% url 'misago:options-confirm-password-change' token=token %}
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_password_form_link.html

@@ -13,6 +13,6 @@ To change your account password click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
 <br>
 <br>
 <br>
 <br>
-<a href="{{ SITE_ADDRESS }}{% url 'misago:forgotten_password_change_form' user_id=recipient.id token=confirmation_token %}">{% trans "Set new password" %}</a>
+<a href="{{ SITE_ADDRESS }}{% url 'misago:forgotten-password-change-form' pk=recipient.pk token=confirmation_token %}">{% trans "Set new password" %}</a>
 <br>
 <br>
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/change_password_form_link.txt

@@ -10,5 +10,5 @@
 {% blocktrans trimmed %}
 {% blocktrans trimmed %}
 To change your account password click the link below:
 To change your account password click the link below:
 {% endblocktrans %}
 {% endblocktrans %}
-{{ SITE_ADDRESS }}{% url 'misago:forgotten_password_change_form' user_id=recipient.id token=confirmation_token %}
+{{ SITE_ADDRESS }}{% url 'misago:forgotten-password-change-form' pk=recipient.pk token=confirmation_token %}
 {% endblock content %}
 {% endblock content %}

+ 1 - 1
misago/templates/misago/emails/register/inactive.html

@@ -24,7 +24,7 @@
   {% endblocktrans %}
   {% endblocktrans %}
   <br>
   <br>
   <br>
   <br>
-  <a href="{{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.id token=activation_token %}">{% trans "Activate my account!" %}</a>
+  <a href="{{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}">{% trans "Activate my account!" %}</a>
   <br>
   <br>
   <br>
   <br>
   {% capture trimmed as login_link %}
   {% capture trimmed as login_link %}

+ 1 - 1
misago/templates/misago/emails/register/inactive.txt

@@ -25,7 +25,7 @@
   {% blocktrans trimmed %}
   {% blocktrans trimmed %}
   Before you will be able to join discussion on our forums, you have to activate your account. To do so, simply click the link below:
   Before you will be able to join discussion on our forums, you have to activate your account. To do so, simply click the link below:
   {% endblocktrans %}
   {% endblocktrans %}
-  {{ SITE_ADDRESS }}{% url 'misago:activate_by_token' user_id=recipient.id token=activation_token %}"
+  {{ SITE_ADDRESS }}{% url 'misago:activate-by-token' pk=recipient.pk token=activation_token %}"
 
 
   {% blocktrans trimmed with login_form=login_link|safe %}
   {% blocktrans trimmed with login_form=login_link|safe %}
   Once your account is activated, you can always sign in to it using the form velow:
   Once your account is activated, you can always sign in to it using the form velow:

+ 2 - 2
misago/templates/misago/footer.html

@@ -19,12 +19,12 @@
         {% endif %}
         {% endif %}
         {% if misago_settings.terms_of_service or misago_settings.terms_of_service_link %}
         {% if misago_settings.terms_of_service or misago_settings.terms_of_service_link %}
           <li>
           <li>
-            <a href="{% url 'misago:terms_of_service' %}">{% trans "Terms of service" %}</a>
+            <a href="{% url 'misago:terms-of-service' %}">{% trans "Terms of service" %}</a>
           </li>
           </li>
         {% endif %}
         {% endif %}
         {% if misago_settings.privacy_policy or misago_settings.privacy_policy_link %}
         {% if misago_settings.privacy_policy or misago_settings.privacy_policy_link %}
           <li>
           <li>
-            <a href="{% url 'misago:privacy_policy' %}">{% trans "Privacy policy" %}</a>
+            <a href="{% url 'misago:privacy-policy' %}">{% trans "Privacy policy" %}</a>
           </li>
           </li>
         {% endif %}
         {% endif %}
         </ul>
         </ul>

+ 1 - 1
misago/templates/misago/forgottenpassword/error.html

@@ -18,7 +18,7 @@
         <p class="lead">{% trans "Can't change forgotten password." %}</p>
         <p class="lead">{% trans "Can't change forgotten password." %}</p>
         <p>{{ message }}</p>
         <p>{{ message }}</p>
         <p>
         <p>
-          <a href="{% url 'misago:forgotten_password' %}">
+          <a href="{% url 'misago:forgotten-password' %}">
             Request another password change link.
             Request another password change link.
           </a>
           </a>
         </p>
         </p>

+ 1 - 1
misago/templates/misago/options/credentials_error.html

@@ -18,7 +18,7 @@
         <p class="lead">{% trans "Change confirmation link is invalid." %}</p>
         <p class="lead">{% trans "Change confirmation link is invalid." %}</p>
         <p>{% trans "The confirmation link belongs to other user, was already used, or has expired." %}</p>
         <p>{% trans "The confirmation link belongs to other user, was already used, or has expired." %}</p>
         <p>
         <p>
-          <a href="{% url 'misago:options_form' form_name='sign-in-credentials' %}">
+          <a href="{% url 'misago:options-form' form_name='sign-in-credentials' %}">
             Request another activation link.
             Request another activation link.
           </a>
           </a>
         </p>
         </p>

+ 1 - 1
misago/templates/misago/profile/header.html

@@ -21,7 +21,7 @@
           <ul class="list-inline">
           <ul class="list-inline">
             {% if profile.rank.is_tab %}
             {% if profile.rank.is_tab %}
             <li class="user-rank">
             <li class="user-rank">
-              <a href="{% url 'misago:users_rank' rank_slug=profile.rank.slug %}" class="item-title">
+              <a href="{% url 'misago:users-rank' slug=profile.rank.slug %}" class="item-title">
                 {{ profile.rank.name }}
                 {{ profile.rank.name }}
               </a>
               </a>
             </li>
             </li>

+ 1 - 1
misago/templates/misago/profile/nav.html

@@ -5,7 +5,7 @@
 
 
 <div class="list-group nav-side">
 <div class="list-group nav-side">
   {% for section in sections %}
   {% for section in sections %}
-    <a href="{% url section.link user_slug=profile.slug user_id=profile.id %}" class="list-group-item{{ section.is_active|iftrue:' active' }}">
+    <a href="{% url section.link slug=profile.slug pk=profile.pk %}" class="list-group-item{{ section.is_active|iftrue:' active' }}">
       <span class="material-icon">
       <span class="material-icon">
         {{ section.icon }}
         {{ section.icon }}
       </span>
       </span>

+ 2 - 2
misago/templates/misago/userslists/active_posters.html

@@ -36,7 +36,7 @@
       <div class="active-posters ui-ready">
       <div class="active-posters ui-ready">
         <ul class="list-group">
         <ul class="list-group">
           {% for ranked in users %}
           {% for ranked in users %}
-            {% url USER_PROFILE_URL user_slug=ranked.slug user_id=ranked.id as user_url %}
+            {% url USER_PROFILE_URL slug=ranked.slug pk=ranked.pk as user_url %}
             <li class="list-group-item{% if ranked.rank.css_class %} list-group-rank-{{ ranked.rank.css_class }}{% endif %}">
             <li class="list-group-item{% if ranked.rank.css_class %} list-group-rank-{{ ranked.rank.css_class }}{% endif %}">
               <div class="rank-user-avatar">
               <div class="rank-user-avatar">
                 <a href="{{ user_url }}">
                 <a href="{{ user_url }}">
@@ -50,7 +50,7 @@
                 </div>
                 </div>
                 <div class="user-details">
                 <div class="user-details">
                   {% if ranked.rank.is_tab %}
                   {% if ranked.rank.is_tab %}
-                  <a href="{% url 'misago:users_rank' rank_slug=ranked.rank.slug %}" class="rank-name item-title">
+                  <a href="{% url 'misago:users-rank' slug=ranked.rank.slug %}" class="rank-name item-title">
                     {{ ranked.rank.name }}
                     {{ ranked.rank.name }}
                   </a>
                   </a>
                   {% else %}
                   {% else %}

+ 5 - 5
misago/templates/misago/userslists/rank.html

@@ -109,7 +109,7 @@ There are {{ users }} users with {{ rank }} rank.
           <ul class="pager">
           <ul class="pager">
             {% if paginator.previous %}
             {% if paginator.previous %}
             <li class="previous">
             <li class="previous">
-              <a href="{% url 'misago:users_rank' rank_slug=rank.slug page=paginator.previous %}">
+              <a href="{% url 'misago:users-rank' slug=rank.slug page=paginator.previous %}">
                 <span aria-hidden="true" class="material-icon">
                 <span aria-hidden="true" class="material-icon">
                   arrow_back
                   arrow_back
                 </span>
                 </span>
@@ -117,7 +117,7 @@ There are {{ users }} users with {{ rank }} rank.
             </li>
             </li>
             {% elif paginator.first %}
             {% elif paginator.first %}
             <li class="previous">
             <li class="previous">
-              <a href="{% url 'misago:users_rank' rank_slug=rank.slug %}">
+              <a href="{% url 'misago:users-rank' slug=rank.slug %}">
                 <span aria-hidden="true" class="material-icon">
                 <span aria-hidden="true" class="material-icon">
                   arrow_back
                   arrow_back
                 </span>
                 </span>
@@ -126,7 +126,7 @@ There are {{ users }} users with {{ rank }} rank.
             {% endif %}
             {% endif %}
             {% if paginator.next %}
             {% if paginator.next %}
             <li class="next">
             <li class="next">
-              <a href="{% url 'misago:users_rank' rank_slug=rank.slug page=paginator.next %}">
+              <a href="{% url 'misago:users-rank' slug=rank.slug page=paginator.next %}">
                 <span aria-hidden="true" class="material-icon">
                 <span aria-hidden="true" class="material-icon">
                   arrow_forward
                   arrow_forward
                 </span>
                 </span>
@@ -138,9 +138,9 @@ There are {{ users }} users with {{ rank }} rank.
             {% for page in paginator.page_range %}
             {% for page in paginator.page_range %}
               <li{% if page == paginator.page %} class="active"{% endif %}>
               <li{% if page == paginator.page %} class="active"{% endif %}>
                 {% if page > 1 %}
                 {% if page > 1 %}
-                <a href="{% url 'misago:users_rank' rank_slug=rank.slug page=page %}">
+                <a href="{% url 'misago:users-rank' slug=rank.slug page=page %}">
                 {% else %}
                 {% else %}
-                <a href="{% url 'misago:users_rank' rank_slug=rank.slug %}">
+                <a href="{% url 'misago:users-rank' slug=rank.slug %}">
                 {% endif %}
                 {% endif %}
                   {{ page }}
                   {{ page }}
                 </a>
                 </a>

+ 2 - 2
misago/threads/serializers/thread.py

@@ -50,8 +50,8 @@ class ThreadSerializer(serializers.ModelSerializer):
     def get_last_poster_url(self, obj):
     def get_last_poster_url(self, obj):
         if obj.last_poster_id:
         if obj.last_poster_id:
             return reverse('misago:user', kwargs={
             return reverse('misago:user', kwargs={
-                'user_slug': obj.last_poster_slug,
-                'user_id': obj.last_poster_id,
+                'slug': obj.last_poster_slug,
+                'pk': obj.last_poster_id,
             })
             })
         else:
         else:
             return None
             return None

+ 2 - 2
misago/threads/threadtypes/thread.py

@@ -11,8 +11,8 @@ class Thread(ThreadTypeBase):
 
 
     def get_category_absolute_url(self, category):
     def get_category_absolute_url(self, category):
         return reverse('misago:category', kwargs={
         return reverse('misago:category', kwargs={
-            'category_id': category.id,
-            'category_slug': category.slug,
+            'pk': category.pk,
+            'slug': category.slug,
         })
         })
 
 
     def get_thread_absolute_url(self, thread):
     def get_thread_absolute_url(self, thread):

+ 7 - 7
misago/threads/urls/__init__.py

@@ -19,7 +19,7 @@ def threads_list_patterns(root_name, view, patterns):
 
 
     for i, pattern in enumerate(patterns):
     for i, pattern in enumerate(patterns):
         if i > 0:
         if i > 0:
-            url_name = '%s_%s' % (root_name, PATTERNS_KWARGS[i]['list_type'])
+            url_name = '%s-%s' % (root_name, PATTERNS_KWARGS[i]['list_type'])
         else:
         else:
             url_name = root_name
             url_name = root_name
 
 
@@ -52,15 +52,15 @@ else:
 
 
 
 
 urlpatterns += threads_list_patterns('category', CategoryThreadsList, (
 urlpatterns += threads_list_patterns('category', CategoryThreadsList, (
-    r'^category/(?P<category_slug>[-a-zA-Z0-9]+)-(?P<category_id>\d+)/$',
-    r'^category/(?P<category_slug>[-a-zA-Z0-9]+)-(?P<category_id>\d+)/my/$',
-    r'^category/(?P<category_slug>[-a-zA-Z0-9]+)-(?P<category_id>\d+)/new/$',
-    r'^category/(?P<category_slug>[-a-zA-Z0-9]+)-(?P<category_id>\d+)/unread/$',
-    r'^category/(?P<category_slug>[-a-zA-Z0-9]+)-(?P<category_id>\d+)/subscribed/$',
+    r'^category/(?P<slug>[-a-zA-Z0-9]+)-(?P<pk>\d+)/$',
+    r'^category/(?P<slug>[-a-zA-Z0-9]+)-(?P<pk>\d+)/my/$',
+    r'^category/(?P<slug>[-a-zA-Z0-9]+)-(?P<pk>\d+)/new/$',
+    r'^category/(?P<slug>[-a-zA-Z0-9]+)-(?P<pk>\d+)/unread/$',
+    r'^category/(?P<slug>[-a-zA-Z0-9]+)-(?P<pk>\d+)/subscribed/$',
 ))
 ))
 
 
 
 
-urlpatterns += threads_list_patterns('private_threads', CategoryThreadsList, (
+urlpatterns += threads_list_patterns('private-threads', CategoryThreadsList, (
     r'^private-threads/$',
     r'^private-threads/$',
     r'^private-threads/my/$',
     r'^private-threads/my/$',
     r'^private-threads/new/$',
     r'^private-threads/new/$',

+ 2 - 2
misago/threads/views/threadslist.py

@@ -148,14 +148,14 @@ class CategoryThreadsList(ThreadsList, ThreadsListMixin):
 
 
     def get_category(self, request, categories, **kwargs):
     def get_category(self, request, categories, **kwargs):
         for category in categories:
         for category in categories:
-            if category.pk == int(kwargs['category_id']):
+            if category.pk == int(kwargs['pk']):
                 if category.special_role:
                 if category.special_role:
                     raise Http404()
                     raise Http404()
 
 
                 allow_see_category(request.user, category)
                 allow_see_category(request.user, category)
                 allow_browse_category(request.user, category)
                 allow_browse_category(request.user, category)
 
 
-                validate_slug(category, kwargs['category_slug'])
+                validate_slug(category, kwargs['slug'])
                 return category
                 return category
         else:
         else:
             raise Http404()
             raise Http404()

+ 0 - 1
misago/urls.py

@@ -8,7 +8,6 @@ urlpatterns = patterns('',
     url(r'^', include('misago.users.urls')),
     url(r'^', include('misago.users.urls')),
     url(r'^', include('misago.categories.urls')),
     url(r'^', include('misago.categories.urls')),
     url(r'^', include('misago.threads.urls')),
     url(r'^', include('misago.threads.urls')),
-    url(r'^', include('misago.readtracker.urls')),
 )
 )
 
 
 urlpatterns += patterns('misago.core.views',
 urlpatterns += patterns('misago.core.views',

+ 68 - 58
misago/users/admin.py

@@ -4,15 +4,15 @@ from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
 
 
 from misago.users.views.admin.bans import BansList, NewBan, EditBan, DeleteBan
 from misago.users.views.admin.bans import BansList, NewBan, EditBan, DeleteBan
-from misago.users.views.admin.ranks import (RanksList, NewRank, EditRank,
-                                            DeleteRank, MoveDownRank,
-                                            MoveUpRank, DefaultRank, RankUsers)
-from misago.users.views.admin.users import (UsersList, NewUser, EditUser,
-                                            DeleteThreadsStep, DeletePostsStep,
-                                            DeleteAccountStep)
-from misago.users.views.admin.warnings import (WarningsList, NewWarning,
-                                               EditWarning, MoveDownWarning,
-                                               MoveUpWarning, DeleteWarning)
+from misago.users.views.admin.ranks import (
+    RanksList, NewRank, EditRank, DeleteRank, MoveDownRank, MoveUpRank,
+    DefaultRank, RankUsers)
+from misago.users.views.admin.users import (
+    UsersList, NewUser, EditUser, DeleteThreadsStep, DeletePostsStep,
+    DeleteAccountStep)
+from misago.users.views.admin.warnings import (
+    WarningsList, NewWarning, EditWarning, MoveDownWarning, MoveUpWarning,
+    DeleteWarning)
 
 
 
 
 class UserAdmin(djadmin.ModelAdmin):
 class UserAdmin(djadmin.ModelAdmin):
@@ -48,10 +48,10 @@ class MisagoAdminExtension(object):
             url(r'^$', UsersList.as_view(), name='index'),
             url(r'^$', UsersList.as_view(), name='index'),
             url(r'^(?P<page>\d+)/$', UsersList.as_view(), name='index'),
             url(r'^(?P<page>\d+)/$', UsersList.as_view(), name='index'),
             url(r'^new/$', NewUser.as_view(), name='new'),
             url(r'^new/$', NewUser.as_view(), name='new'),
-            url(r'^edit/(?P<user_id>\d+)/$', EditUser.as_view(), name='edit'),
-            url(r'^delete-threads/(?P<user_id>\d+)/$', DeleteThreadsStep.as_view(), name='delete_threads'),
-            url(r'^delete-posts/(?P<user_id>\d+)/$', DeletePostsStep.as_view(), name='delete_posts'),
-            url(r'^delete-account/(?P<user_id>\d+)/$', DeleteAccountStep.as_view(), name='delete_account'),
+            url(r'^edit/(?P<pk>\d+)/$', EditUser.as_view(), name='edit'),
+            url(r'^delete-threads/(?P<pk>\d+)/$', DeleteThreadsStep.as_view(), name='delete-threads'),
+            url(r'^delete-posts/(?P<pk>\d+)/$', DeletePostsStep.as_view(), name='delete-posts'),
+            url(r'^delete-account/(?P<pk>\d+)/$', DeleteAccountStep.as_view(), name='delete-account'),
         )
         )
 
 
         # Ranks
         # Ranks
@@ -59,12 +59,12 @@ class MisagoAdminExtension(object):
         urlpatterns.patterns('users:ranks',
         urlpatterns.patterns('users:ranks',
             url(r'^$', RanksList.as_view(), name='index'),
             url(r'^$', RanksList.as_view(), name='index'),
             url(r'^new/$', NewRank.as_view(), name='new'),
             url(r'^new/$', NewRank.as_view(), name='new'),
-            url(r'^edit/(?P<rank_id>\d+)/$', EditRank.as_view(), name='edit'),
-            url(r'^default/(?P<rank_id>\d+)/$', DefaultRank.as_view(), name='default'),
-            url(r'^move/down/(?P<rank_id>\d+)/$', MoveDownRank.as_view(), name='down'),
-            url(r'^move/up/(?P<rank_id>\d+)/$', MoveUpRank.as_view(), name='up'),
-            url(r'^users/(?P<rank_id>\d+)/$', RankUsers.as_view(), name='users'),
-            url(r'^delete/(?P<rank_id>\d+)/$', DeleteRank.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditRank.as_view(), name='edit'),
+            url(r'^default/(?P<pk>\d+)/$', DefaultRank.as_view(), name='default'),
+            url(r'^move/down/(?P<pk>\d+)/$', MoveDownRank.as_view(), name='down'),
+            url(r'^move/up/(?P<pk>\d+)/$', MoveUpRank.as_view(), name='up'),
+            url(r'^users/(?P<pk>\d+)/$', RankUsers.as_view(), name='users'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteRank.as_view(), name='delete'),
         )
         )
 
 
         # Bans
         # Bans
@@ -73,8 +73,8 @@ class MisagoAdminExtension(object):
             url(r'^$', BansList.as_view(), name='index'),
             url(r'^$', BansList.as_view(), name='index'),
             url(r'^(?P<page>\d+)/$', BansList.as_view(), name='index'),
             url(r'^(?P<page>\d+)/$', BansList.as_view(), name='index'),
             url(r'^new/$', NewBan.as_view(), name='new'),
             url(r'^new/$', NewBan.as_view(), name='new'),
-            url(r'^edit/(?P<ban_id>\d+)/$', EditBan.as_view(), name='edit'),
-            url(r'^delete/(?P<ban_id>\d+)/$', DeleteBan.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditBan.as_view(), name='edit'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteBan.as_view(), name='delete'),
         )
         )
 
 
         # Warnings
         # Warnings
@@ -82,43 +82,53 @@ class MisagoAdminExtension(object):
         urlpatterns.patterns('users:warnings',
         urlpatterns.patterns('users:warnings',
             url(r'^$', WarningsList.as_view(), name='index'),
             url(r'^$', WarningsList.as_view(), name='index'),
             url(r'^new/$', NewWarning.as_view(), name='new'),
             url(r'^new/$', NewWarning.as_view(), name='new'),
-            url(r'^edit/(?P<warning_id>\d+)/$', EditWarning.as_view(), name='edit'),
-            url(r'^move/down/(?P<warning_id>\d+)/$', MoveDownWarning.as_view(), name='down'),
-            url(r'^move/up/(?P<warning_id>\d+)/$', MoveUpWarning.as_view(), name='up'),
-            url(r'^delete/(?P<warning_id>\d+)/$', DeleteWarning.as_view(), name='delete'),
+            url(r'^edit/(?P<pk>\d+)/$', EditWarning.as_view(), name='edit'),
+            url(r'^move/down/(?P<pk>\d+)/$', MoveDownWarning.as_view(), name='down'),
+            url(r'^move/up/(?P<pk>\d+)/$', MoveUpWarning.as_view(), name='up'),
+            url(r'^delete/(?P<pk>\d+)/$', DeleteWarning.as_view(), name='delete'),
         )
         )
 
 
     def register_navigation_nodes(self, site):
     def register_navigation_nodes(self, site):
-        site.add_node(name=_("Users"),
-                      icon='fa fa-users',
-                      parent='misago:admin',
-                      after='misago:admin:index',
-                      namespace='misago:admin:users',
-                      link='misago:admin:users:accounts:index')
-
-        site.add_node(name=_("User Accounts"),
-                      icon='fa fa-users',
-                      parent='misago:admin:users',
-                      namespace='misago:admin:users:accounts',
-                      link='misago:admin:users:accounts:index')
-
-        site.add_node(name=_("Ranks"),
-                      icon='fa fa-graduation-cap',
-                      parent='misago:admin:users',
-                      after='misago:admin:users:accounts:index',
-                      namespace='misago:admin:users:ranks',
-                      link='misago:admin:users:ranks:index')
-
-        site.add_node(name=_("Bans"),
-                      icon='fa fa-lock',
-                      parent='misago:admin:users',
-                      after='misago:admin:users:ranks:index',
-                      namespace='misago:admin:users:bans',
-                      link='misago:admin:users:bans:index')
-
-        site.add_node(name=_("Warning levels"),
-                      icon='fa fa-exclamation-triangle',
-                      parent='misago:admin:users',
-                      after='misago:admin:users:bans:index',
-                      namespace='misago:admin:users:warnings',
-                      link='misago:admin:users:warnings:index')
+        site.add_node(
+            name=_("Users"),
+            icon='fa fa-users',
+            parent='misago:admin',
+            after='misago:admin:index',
+            namespace='misago:admin:users',
+            link='misago:admin:users:accounts:index',
+        )
+
+        site.add_node(
+            name=_("User Accounts"),
+            icon='fa fa-users',
+            parent='misago:admin:users',
+            namespace='misago:admin:users:accounts',
+            link='misago:admin:users:accounts:index',
+        )
+
+        site.add_node(
+            name=_("Ranks"),
+            icon='fa fa-graduation-cap',
+            parent='misago:admin:users',
+            after='misago:admin:users:accounts:index',
+            namespace='misago:admin:users:ranks',
+            link='misago:admin:users:ranks:index',
+        )
+
+        site.add_node(
+            name=_("Bans"),
+            icon='fa fa-lock',
+            parent='misago:admin:users',
+            after='misago:admin:users:ranks:index',
+            namespace='misago:admin:users:bans',
+            link='misago:admin:users:bans:index',
+        )
+
+        site.add_node(
+            name=_("Warning levels"),
+            icon='fa fa-exclamation-triangle',
+            parent='misago:admin:users',
+            after='misago:admin:users:bans:index',
+            namespace='misago:admin:users:warnings',
+            link='misago:admin:users:warnings:index',
+        )

+ 2 - 2
misago/users/api/auth.py

@@ -136,7 +136,7 @@ class PasswordChangeFailed(Exception):
 @api_view(['POST'])
 @api_view(['POST'])
 @permission_classes((UnbannedOnly,))
 @permission_classes((UnbannedOnly,))
 @csrf_protect
 @csrf_protect
-def change_forgotten_password(request, user_id, token):
+def change_forgotten_password(request, pk, token):
     User = auth.get_user_model()
     User = auth.get_user_model()
 
 
     invalid_message = _("Form link is invalid. Please try again.")
     invalid_message = _("Form link is invalid. Please try again.")
@@ -144,7 +144,7 @@ def change_forgotten_password(request, user_id, token):
 
 
     try:
     try:
         try:
         try:
-            user = User.objects.get(pk=user_id)
+            user = User.objects.get(pk=pk)
         except User.DoesNotExist:
         except User.DoesNotExist:
             raise PasswordChangeFailed(invalid_message)
             raise PasswordChangeFailed(invalid_message)
 
 

+ 5 - 4
misago/users/api/usernamechanges.py

@@ -17,11 +17,11 @@ from misago.users.serializers.usernamechange import UsernameChangeSerializer
 class UsernameChangesViewSetPermission(BasePermission):
 class UsernameChangesViewSetPermission(BasePermission):
     def has_permission(self, request, view):
     def has_permission(self, request, view):
         try:
         try:
-            user_id = int(request.GET.get('user'))
+            user_pk = int(request.GET.get('user'))
         except (ValueError, TypeError):
         except (ValueError, TypeError):
-            user_id = -1
+            user_pk = -1
 
 
-        if user_id == request.user.pk:
+        if user_pk == request.user.pk:
             return True
             return True
         elif not request.user.acl.get('can_see_users_name_history'):
         elif not request.user.acl.get('can_see_users_name_history'):
             raise PermissionDenied(_("You don't have permission to "
             raise PermissionDenied(_("You don't have permission to "
@@ -48,6 +48,7 @@ class UsernameChangesViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
                 queryset = queryset.filter(
                 queryset = queryset.filter(
                     Q(changed_by_username__istartswith=search_phrase) |
                     Q(changed_by_username__istartswith=search_phrase) |
                     Q(new_username__istartswith=search_phrase) |
                     Q(new_username__istartswith=search_phrase) |
-                    Q(old_username__istartswith=search_phrase))
+                    Q(old_username__istartswith=search_phrase)
+                )
 
 
         return queryset.select_related('user', 'changed_by').order_by('-id')
         return queryset.select_related('user', 'changed_by').order_by('-id')

+ 4 - 4
misago/users/api/users.py

@@ -68,9 +68,9 @@ class UserViewSet(viewsets.GenericViewSet):
         relations = ('rank', 'online_tracker', 'ban_cache')
         relations = ('rank', 'online_tracker', 'ban_cache')
         return self.queryset.select_related(*relations)
         return self.queryset.select_related(*relations)
 
 
-    def get_user(self, user_id):
+    def get_user(self, pk):
         return get_object_or_404(self.get_queryset(),
         return get_object_or_404(self.get_queryset(),
-            id=get_int_or_404(user_id)
+            pk=get_int_or_404(pk)
         )
         )
 
 
     def list(self, request):
     def list(self, request):
@@ -228,9 +228,9 @@ class UserViewSet(viewsets.GenericViewSet):
                         post.thread.save()
                         post.thread.save()
 
 
                     categories = Category.objects.filter(
                     categories = Category.objects.filter(
-                        id__in=categories_to_sync).iterator()
+                        id__in=categories_to_sync)
 
 
-                    for category in categories:
+                    for category in categories.iterator():
                         category.synchronize()
                         category.synchronize()
                         category.save()
                         category.save()
 
 

+ 28 - 27
misago/users/apps.py

@@ -20,26 +20,27 @@ class MisagoUsersConfig(AppConfig):
             return request.user.acl['can_have_signature']
             return request.user.acl['can_have_signature']
 
 
         usercp.add_section(
         usercp.add_section(
-            link='misago:usercp_change_forum_options',
+            link='misago:usercp-change-forum-options',
             name=_('Forum options'),
             name=_('Forum options'),
             component='forum-options',
             component='forum-options',
-            icon='settings')
-
+            icon='settings',
+        )
         usercp.add_section(
         usercp.add_section(
-            link='misago:usercp_change_username',
+            link='misago:usercp-change-username',
             name=_('Change username'),
             name=_('Change username'),
             component='change-username',
             component='change-username',
-            icon='card_membership')
-
+            icon='card_membership',
+        )
         usercp.add_section(
         usercp.add_section(
-            link='misago:usercp_change_email_password',
+            link='misago:usercp-change-email-password',
             name=_('Change email or password'),
             name=_('Change email or password'),
             component='sign-in-credentials',
             component='sign-in-credentials',
-            icon='vpn_key')
+            icon='vpn_key',
+        )
 
 
     def register_default_users_list_pages(self):
     def register_default_users_list_pages(self):
         users_list.add_section(
         users_list.add_section(
-            link='misago:users_active_posters',
+            link='misago:users-active-posters',
             component='active-posters',
             component='active-posters',
             name=_('Active posters'))
             name=_('Active posters'))
 
 
@@ -87,44 +88,44 @@ class MisagoUsersConfig(AppConfig):
                 return False
                 return False
 
 
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:user_posts',
+            link='misago:user-posts',
             name=_("Posts"),
             name=_("Posts"),
             icon='message',
             icon='message',
             component='posts',
             component='posts',
-            get_metadata=posts_badge)
-
+            get_metadata=posts_badge,
+        )
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:user_threads',
+            link='misago:user-threads',
             name=_("Threads"),
             name=_("Threads"),
             icon='forum',
             icon='forum',
             component='threads',
             component='threads',
-            get_metadata=threads_badge)
-
+            get_metadata=threads_badge,
+        )
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:user_followers',
+            link='misago:user-followers',
             name=_("Followers"),
             name=_("Followers"),
             icon='favorite',
             icon='favorite',
             component='followers',
             component='followers',
-            get_metadata=followers_badge)
-
+            get_metadata=followers_badge,
+        )
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:user_follows',
+            link='misago:user-follows',
             name=_("Follows"),
             name=_("Follows"),
             icon='favorite_border',
             icon='favorite_border',
             component='follows',
             component='follows',
-            get_metadata=following_badge)
-
+            get_metadata=following_badge,
+        )
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:username_history',
+            link='misago:username-history',
             name=_("Username history"),
             name=_("Username history"),
             icon='card_membership',
             icon='card_membership',
             component='username-history',
             component='username-history',
-            visible_if=can_see_names_history)
-
+            visible_if=can_see_names_history,
+        )
         user_profile.add_section(
         user_profile.add_section(
-            link='misago:user_ban',
+            link='misago:user-ban',
             name=_("Ban details"),
             name=_("Ban details"),
             icon='remove_circle_outline',
             icon='remove_circle_outline',
             component='ban-details',
             component='ban-details',
-            visible_if=can_see_ban_details)
-
+            visible_if=can_see_ban_details,
+        )

+ 2 - 2
misago/users/authbackends.py

@@ -18,11 +18,11 @@ class MisagoBackend(ModelBackend):
             # difference between an existing and a non-existing user (#20760).
             # difference between an existing and a non-existing user (#20760).
             UserModel().set_password(password)
             UserModel().set_password(password)
 
 
-    def get_user(self, user_id):
+    def get_user(self, pk):
         UserModel = get_user_model()
         UserModel = get_user_model()
         try:
         try:
             manager = UserModel._default_manager
             manager = UserModel._default_manager
             relations = ('rank', 'online_tracker', 'ban_cache')
             relations = ('rank', 'online_tracker', 'ban_cache')
-            return manager.select_related(*relations).get(pk=user_id)
+            return manager.select_related(*relations).get(pk=pk)
         except UserModel.DoesNotExist:
         except UserModel.DoesNotExist:
             return None
             return None

+ 3 - 3
misago/users/avatars/store.py

@@ -108,11 +108,11 @@ def store_new_avatar(user, image):
 def get_avatars_dir_path(user=None):
 def get_avatars_dir_path(user=None):
     if user:
     if user:
         try:
         try:
-            user_id = user.pk
+            user_pk = user.pk
         except AttributeError:
         except AttributeError:
-            user_id = user
+            user_pk = user
 
 
-        dir_hash = md5(str(user_id)).hexdigest()
+        dir_hash = md5(str(user_pk)).hexdigest()
         hash_path = [dir_hash[0:1], dir_hash[2:3]]
         hash_path = [dir_hash[0:1], dir_hash[2:3]]
         return Path(os.path.join(AVATARS_STORE, *hash_path))
         return Path(os.path.join(AVATARS_STORE, *hash_path))
     else:
     else:

+ 3 - 3
misago/users/context_processors.py

@@ -7,8 +7,8 @@ from misago.users.serializers import (
 
 
 def user_links(request):
 def user_links(request):
     request.frontend_context.update({
     request.frontend_context.update({
-        'REQUEST_ACTIVATION_URL': reverse('misago:request_activation'),
-        'FORGOTTEN_PASSWORD_URL': reverse('misago:forgotten_password'),
+        'REQUEST_ACTIVATION_URL': reverse('misago:request-activation'),
+        'FORGOTTEN_PASSWORD_URL': reverse('misago:forgotten-password'),
 
 
         'BANNED_URL': reverse('misago:banned'),
         'BANNED_URL': reverse('misago:banned'),
 
 
@@ -18,7 +18,7 @@ def user_links(request):
         'AUTH_API': reverse('misago:api:auth'),
         'AUTH_API': reverse('misago:api:auth'),
         'USERS_API': reverse('misago:api:user-list'),
         'USERS_API': reverse('misago:api:user-list'),
 
 
-        'CAPTCHA_API': reverse('misago:api:captcha_question'),
+        'CAPTCHA_API': reverse('misago:api:captcha-question'),
         'USERNAME_CHANGES_API': reverse('misago:api:usernamechange-list'),
         'USERNAME_CHANGES_API': reverse('misago:api:usernamechange-list'),
     })
     })
 
 

+ 2 - 4
misago/users/forms/admin.py

@@ -238,12 +238,10 @@ class SearchUsersFormBase(forms.Form):
                 email__istartswith=criteria.get('email'))
                 email__istartswith=criteria.get('email'))
 
 
         if criteria.get('rank'):
         if criteria.get('rank'):
-            queryset = queryset.filter(
-                rank_id=criteria.get('rank'))
+            queryset = queryset.filter(rank_id=criteria.get('rank'))
 
 
         if criteria.get('role'):
         if criteria.get('role'):
-            queryset = queryset.filter(
-                roles__id=criteria.get('role'))
+            queryset = queryset.filter(roles__id=criteria.get('role'))
 
 
         if criteria.get('inactive'):
         if criteria.get('inactive'):
             queryset = queryset.filter(requires_activation__gt=0)
             queryset = queryset.filter(requires_activation__gt=0)

+ 1 - 3
misago/users/models/rank.py

@@ -52,9 +52,7 @@ class Rank(models.Model):
         return super(Rank, self).delete(*args, **kwargs)
         return super(Rank, self).delete(*args, **kwargs)
 
 
     def get_absolute_url(self):
     def get_absolute_url(self):
-        return reverse('misago:users_rank', kwargs={
-            'rank_slug': self.slug
-        })
+        return reverse('misago:users-rank', kwargs={'slug': self.slug})
 
 
     def set_name(self, name):
     def set_name(self, name):
         self.name = name
         self.name = name

+ 24 - 17
misago/users/models/user.py

@@ -148,8 +148,10 @@ class UserManager(BaseUserManager):
     def create_superuser(self, username, email, password,
     def create_superuser(self, username, email, password,
                          set_default_avatar=False):
                          set_default_avatar=False):
         with transaction.atomic():
         with transaction.atomic():
-            user = self.create_user(username, email, password=password,
-                                    set_default_avatar=set_default_avatar)
+            user = self.create_user(username, email,
+                password=password,
+                set_default_avatar=set_default_avatar,
+            )
 
 
             try:
             try:
                 user.rank = Rank.objects.get(name=_("Forum team"))
                 user.rank = Rank.objects.get(name=_("Forum team"))
@@ -268,7 +270,7 @@ class User(AbstractBaseUser, PermissionsMixin):
 
 
     def lock(self):
     def lock(self):
         """Locks user in DB"""
         """Locks user in DB"""
-        return User.objects.select_for_update().get(id=self.id)
+        return User.objects.select_for_update().get(pk=self.pk)
 
 
     def delete(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
         if kwargs.pop('delete_content', False):
         if kwargs.pop('delete_content', False):
@@ -352,8 +354,8 @@ class User(AbstractBaseUser, PermissionsMixin):
 
 
     def get_absolute_url(self):
     def get_absolute_url(self):
         return reverse('misago:user', kwargs={
         return reverse('misago:user', kwargs={
-            'user_slug': self.slug,
-            'user_id': self.id,
+            'slug': self.slug,
+            'pk': self.pk,
         })
         })
 
 
     def get_username(self):
     def get_username(self):
@@ -383,10 +385,12 @@ class User(AbstractBaseUser, PermissionsMixin):
                 username_changed.send(sender=self)
                 username_changed.send(sender=self)
 
 
     def record_name_change(self, changed_by, new_username, old_username):
     def record_name_change(self, changed_by, new_username, old_username):
-        self.namechanges.create(new_username=new_username,
-                                old_username=old_username,
-                                changed_by=changed_by,
-                                changed_by_username=changed_by.username)
+        self.namechanges.create(
+            new_username=new_username,
+            old_username=old_username,
+            changed_by=changed_by,
+            changed_by_username=changed_by.username,
+        )
 
 
     def set_email(self, new_email):
     def set_email(self, new_email):
         self.email = UserManager.normalize_email(new_email)
         self.email = UserManager.normalize_email(new_email)
@@ -428,22 +432,24 @@ class User(AbstractBaseUser, PermissionsMixin):
 
 
     def is_following(self, user):
     def is_following(self, user):
         try:
         try:
-            self.follows.get(id=user.pk)
+            self.follows.get(pk=user.pk)
             return True
             return True
         except User.DoesNotExist:
         except User.DoesNotExist:
             return False
             return False
 
 
     def is_blocking(self, user):
     def is_blocking(self, user):
         try:
         try:
-            self.blocks.get(id=user.pk)
+            self.blocks.get(pk=user.pk)
             return True
             return True
         except User.DoesNotExist:
         except User.DoesNotExist:
             return False
             return False
 
 
 
 
 class Online(models.Model):
 class Online(models.Model):
-    user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True,
-                                related_name='online_tracker')
+    user = models.OneToOneField(settings.AUTH_USER_MODEL,
+        primary_key=True,
+        related_name='online_tracker',
+    )
     current_ip = models.GenericIPAddressField()
     current_ip = models.GenericIPAddressField()
     last_click = models.DateTimeField(default=timezone.now)
     last_click = models.DateTimeField(default=timezone.now)
 
 
@@ -456,11 +462,12 @@ class Online(models.Model):
 
 
 class UsernameChange(models.Model):
 class UsernameChange(models.Model):
     user = models.ForeignKey(settings.AUTH_USER_MODEL,
     user = models.ForeignKey(settings.AUTH_USER_MODEL,
-                             related_name='namechanges')
+        related_name='namechanges')
     changed_by = models.ForeignKey(settings.AUTH_USER_MODEL,
     changed_by = models.ForeignKey(settings.AUTH_USER_MODEL,
-                                   null=True, blank=True,
-                                   related_name='user_renames',
-                                   on_delete=models.SET_NULL)
+        null=True, blank=True,
+        related_name='user_renames',
+        on_delete=models.SET_NULL,
+    )
     changed_by_username = models.CharField(max_length=30)
     changed_by_username = models.CharField(max_length=30)
     changed_on = models.DateTimeField(default=timezone.now)
     changed_on = models.DateTimeField(default=timezone.now)
     new_username = models.CharField(max_length=255)
     new_username = models.CharField(max_length=255)

+ 3 - 3
misago/users/templatetags/misago_avatars.py

@@ -7,8 +7,8 @@ register = template.Library()
 
 
 @register.filter(name='avatar')
 @register.filter(name='avatar')
 def avatar(user, size=200):
 def avatar(user, size=200):
-    return reverse('misago:user_avatar', kwargs={
-        'user_id': user.id,
+    return reverse('misago:user-avatar', kwargs={
+        'pk': user.pk,
         'hash': user.avatar_hash,
         'hash': user.avatar_hash,
         'size': size
         'size': size
     })
     })
@@ -16,4 +16,4 @@ def avatar(user, size=200):
 
 
 @register.simple_tag
 @register.simple_tag
 def blankavatar(size=200):
 def blankavatar(size=200):
-    return reverse('misago:blank_avatar', kwargs={'size': size})
+    return reverse('misago:blank-avatar', kwargs={'size': size})

+ 22 - 20
misago/users/tests/test_activation_views.py

@@ -9,7 +9,7 @@ from misago.users.tokens import make_activation_token
 class ActivationViewsTests(TestCase):
 class ActivationViewsTests(TestCase):
     def test_request_view_returns_200(self):
     def test_request_view_returns_200(self):
         """request new activation link view returns 200"""
         """request new activation link view returns 200"""
-        response = self.client.get(reverse('misago:request_activation'))
+        response = self.client.get(reverse('misago:request-activation'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
     def test_view_activate_banned(self):
     def test_view_activate_banned(self):
@@ -17,16 +17,18 @@ class ActivationViewsTests(TestCase):
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123',
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123',
                                              requires_activation=1)
                                              requires_activation=1)
-        Ban.objects.create(check_type=BAN_USERNAME,
-                           banned_value='bob',
-                           user_message='Nope!')
+        Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value='bob',
+            user_message='Nope!',
+        )
 
 
         activation_token = make_activation_token(test_user)
         activation_token = make_activation_token(test_user)
 
 
-        response = self.client.get(
-            reverse('misago:activate_by_token',
-                    kwargs={'user_id': test_user.pk,
-                            'token': activation_token}))
+        response = self.client.get(reverse('misago:activate-by-token', kwargs={
+            'pk': test_user.pk,
+            'token': activation_token,
+        }))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn("<p>Nope!</p>", response.content)
         self.assertIn("<p>Nope!</p>", response.content)
 
 
@@ -41,10 +43,10 @@ class ActivationViewsTests(TestCase):
 
 
         activation_token = make_activation_token(test_user)
         activation_token = make_activation_token(test_user)
 
 
-        response = self.client.get(
-            reverse('misago:activate_by_token',
-                    kwargs={'user_id': test_user.pk,
-                            'token': activation_token + 'acd'}))
+        response = self.client.get(reverse('misago:activate-by-token', kwargs={
+            'pk': test_user.pk,
+            'token': activation_token + 'acd',
+        }))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
 
 
         test_user = User.objects.get(pk=test_user.pk)
         test_user = User.objects.get(pk=test_user.pk)
@@ -57,10 +59,10 @@ class ActivationViewsTests(TestCase):
 
 
         activation_token = make_activation_token(test_user)
         activation_token = make_activation_token(test_user)
 
 
-        response = self.client.get(
-            reverse('misago:activate_by_token',
-                    kwargs={'user_id': test_user.pk,
-                            'token': activation_token}))
+        response = self.client.get(reverse('misago:activate-by-token', kwargs={
+            'pk': test_user.pk,
+            'token': activation_token,
+        }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
         test_user = User.objects.get(pk=test_user.pk)
         test_user = User.objects.get(pk=test_user.pk)
@@ -74,10 +76,10 @@ class ActivationViewsTests(TestCase):
 
 
         activation_token = make_activation_token(test_user)
         activation_token = make_activation_token(test_user)
 
 
-        response = self.client.get(
-            reverse('misago:activate_by_token',
-                    kwargs={'user_id': test_user.pk,
-                            'token': activation_token}))
+        response = self.client.get(reverse('misago:activate-by-token', kwargs={
+            'pk': test_user.pk,
+            'token': activation_token,
+        }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn("your account has been activated!", response.content)
         self.assertIn("your account has been activated!", response.content)
 
 

+ 47 - 35
misago/users/tests/test_auth_api.py

@@ -30,9 +30,10 @@ class GatewayTests(TestCase):
         User = get_user_model()
         User = get_user_model()
         user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
         user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
 
 
-        response = self.client.post(
-            '/api/auth/',
-            data={'username': 'Bob', 'password': 'Pass.123'})
+        response = self.client.post('/api/auth/', data={
+            'username': 'Bob',
+            'password': 'Pass.123',
+        })
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
@@ -54,13 +55,16 @@ class GatewayTests(TestCase):
         User = get_user_model()
         User = get_user_model()
         User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
         User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
 
 
-        ban = Ban.objects.create(check_type=BAN_USERNAME,
-                                 banned_value='bob',
-                                 user_message='You are tragically banned.')
+        ban = Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value='bob',
+            user_message='You are tragically banned.',
+        )
 
 
-        response = self.client.post(
-            '/api/auth/',
-            data={'username': 'Bob', 'password': 'Pass.123'})
+        response = self.client.post('/api/auth/', data={
+            'username': 'Bob',
+            'password': 'Pass.123',
+        })
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
 
 
         response_json = json.loads(response.content)
         response_json = json.loads(response.content)
@@ -79,12 +83,13 @@ class GatewayTests(TestCase):
     def test_login_inactive_admin(self):
     def test_login_inactive_admin(self):
         """login api fails to sign admin-activated user in"""
         """login api fails to sign admin-activated user in"""
         User = get_user_model()
         User = get_user_model()
-        User.objects.create_user('Bob', 'bob@test.com', 'Pass.123',
-                                 requires_activation=1)
+        User.objects.create_user(
+            'Bob', 'bob@test.com', 'Pass.123', requires_activation=1)
 
 
-        response = self.client.post(
-            '/api/auth/',
-            data={'username': 'Bob', 'password': 'Pass.123'})
+        response = self.client.post('/api/auth/', data={
+            'username': 'Bob',
+            'password': 'Pass.123',
+        })
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
 
 
         response_json = json.loads(response.content)
         response_json = json.loads(response.content)
@@ -99,12 +104,13 @@ class GatewayTests(TestCase):
     def test_login_inactive_user(self):
     def test_login_inactive_user(self):
         """login api fails to sign user-activated user in"""
         """login api fails to sign user-activated user in"""
         User = get_user_model()
         User = get_user_model()
-        User.objects.create_user('Bob', 'bob@test.com', 'Pass.123',
-                                 requires_activation=2)
+        User.objects.create_user(
+            'Bob', 'bob@test.com', 'Pass.123', requires_activation=2)
 
 
-        response = self.client.post(
-            '/api/auth/',
-            data={'username': 'Bob', 'password': 'Pass.123'})
+        response = self.client.post('/api/auth/', data={
+            'username': 'Bob',
+            'password': 'Pass.123',
+        })
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
 
 
         response_json = json.loads(response.content)
         response_json = json.loads(response.content)
@@ -135,9 +141,11 @@ class SendActivationAPITests(TestCase):
 
 
     def test_submit_banned(self):
     def test_submit_banned(self):
         """request activation link api passes for banned users"""
         """request activation link api passes for banned users"""
-        Ban.objects.create(check_type=BAN_USERNAME,
-                           banned_value=self.user.username,
-                           user_message='Nope!')
+        Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value=self.user.username,
+            user_message='Nope!',
+        )
 
 
         response = self.client.post(self.link, data={'email': self.user.email})
         response = self.client.post(self.link, data={'email': self.user.email})
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -207,9 +215,11 @@ class SendPasswordFormAPITests(TestCase):
 
 
     def test_submit_banned(self):
     def test_submit_banned(self):
         """request change password form link api sends reset link mail"""
         """request change password form link api sends reset link mail"""
-        Ban.objects.create(check_type=BAN_USERNAME,
-                           banned_value=self.user.username,
-                           user_message='Nope!')
+        Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value=self.user.username,
+            user_message='Nope!',
+        )
 
 
         response = self.client.post(self.link, data={'email': self.user.email})
         response = self.client.post(self.link, data={'email': self.user.email})
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -261,18 +271,18 @@ class ChangePasswordAPITests(TestCase):
     def test_submit_valid(self):
     def test_submit_valid(self):
         """submit change password form api errors for empty body"""
         """submit change password form api errors for empty body"""
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 make_password_change_token(self.user)
                 make_password_change_token(self.user)
             ), data={'password': 'n3wp4ss!'})
             ), data={'password': 'n3wp4ss!'})
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
-        user = get_user_model().objects.get(id=self.user.id)
+        user = get_user_model().objects.get(id=self.user.pk)
         self.assertTrue(user.check_password('n3wp4ss!'))
         self.assertTrue(user.check_password('n3wp4ss!'))
 
 
     def test_invalid_token_link(self):
     def test_invalid_token_link(self):
         """request errors on invalid user id link"""
         """request errors on invalid user id link"""
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 'asda7ad89sa7d9s789as'
                 'asda7ad89sa7d9s789as'
             ))
             ))
 
 
@@ -281,12 +291,14 @@ class ChangePasswordAPITests(TestCase):
 
 
     def test_banned_user_link(self):
     def test_banned_user_link(self):
         """request errors because user is banned"""
         """request errors because user is banned"""
-        Ban.objects.create(check_type=BAN_USERNAME,
-                           banned_value=self.user.username,
-                           user_message='Nope!')
+        Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value=self.user.username,
+            user_message='Nope!',
+        )
 
 
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 make_password_change_token(self.user)
                 make_password_change_token(self.user)
             ))
             ))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -298,7 +310,7 @@ class ChangePasswordAPITests(TestCase):
         self.user.save()
         self.user.save()
 
 
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 make_password_change_token(self.user)
                 make_password_change_token(self.user)
             ))
             ))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -308,7 +320,7 @@ class ChangePasswordAPITests(TestCase):
         self.user.save()
         self.user.save()
 
 
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 make_password_change_token(self.user)
                 make_password_change_token(self.user)
             ))
             ))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
@@ -317,7 +329,7 @@ class ChangePasswordAPITests(TestCase):
     def test_submit_empty(self):
     def test_submit_empty(self):
         """submit change password form api errors for empty body"""
         """submit change password form api errors for empty body"""
         response = self.client.post(self.link % (
         response = self.client.post(self.link % (
-                self.user.id,
+                self.user.pk,
                 make_password_change_token(self.user)
                 make_password_change_token(self.user)
             ))
             ))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)

+ 9 - 8
misago/users/tests/test_avatarserver_views.py

@@ -13,10 +13,10 @@ class AvatarServerTests(TestCase):
         test_user = User.objects.create_user('Bob', 'bob@bob.com', 'pass123',
         test_user = User.objects.create_user('Bob', 'bob@bob.com', 'pass123',
                                              set_default_avatar=True)
                                              set_default_avatar=True)
 
 
-        avatar_url = reverse('misago:user_avatar', kwargs={
+        avatar_url = reverse('misago:user-avatar', kwargs={
+            'pk': test_user.pk,
             'hash': test_user.avatar_hash,
             'hash': test_user.avatar_hash,
-            'user_id': test_user.pk,
-            'size': 150
+            'size': 150,
         })
         })
         response = self.client.get(avatar_url)
         response = self.client.get(avatar_url)
 
 
@@ -25,10 +25,10 @@ class AvatarServerTests(TestCase):
 
 
     def test_deleted_user_avatar_serving(self):
     def test_deleted_user_avatar_serving(self):
         """avatar server handles deleted user avatar requests"""
         """avatar server handles deleted user avatar requests"""
-        avatar_url = reverse('misago:user_avatar', kwargs={
+        avatar_url = reverse('misago:user-avatar', kwargs={
+            'pk': 12345,
             'hash': '12356af',
             'hash': '12356af',
-            'user_id': 12345,
-            'size': 150
+            'size': 150,
         })
         })
         response = self.client.get(avatar_url)
         response = self.client.get(avatar_url)
 
 
@@ -37,8 +37,9 @@ class AvatarServerTests(TestCase):
 
 
     def test_blank_avatar_serving(self):
     def test_blank_avatar_serving(self):
         """avatar server handles blank avatar requests"""
         """avatar server handles blank avatar requests"""
-        response = self.client.get(reverse('misago:blank_avatar',
-                                           kwargs={'size': 150}))
+        response = self.client.get(reverse('misago:blank-avatar', kwargs={
+            'size': 150,
+        }))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response['Content-Type'], 'image/png')
         self.assertEqual(response['Content-Type'], 'image/png')

+ 4 - 4
misago/users/tests/test_banadmin_views.py

@@ -88,8 +88,7 @@ class BanAdminViewsTests(AdminTestCase):
 
 
         test_ban = Ban.objects.get(banned_value='admin')
         test_ban = Ban.objects.get(banned_value='admin')
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:users:bans:edit',
-                    kwargs={'ban_id': test_ban.pk}),
+            reverse('misago:admin:users:bans:edit', kwargs={'pk': test_ban.pk}),
             data={
             data={
                 'check_type': '1',
                 'check_type': '1',
                 'banned_value': 'test@test.com',
                 'banned_value': 'test@test.com',
@@ -116,8 +115,9 @@ class BanAdminViewsTests(AdminTestCase):
         test_ban = Ban.objects.get(banned_value='testban')
         test_ban = Ban.objects.get(banned_value='testban')
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:admin:users:bans:delete',
-                    kwargs={'ban_id': test_ban.pk}))
+            reverse('misago:admin:users:bans:delete', kwargs={
+                'pk': test_ban.pk
+            }))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         response = self.client.get(reverse('misago:admin:users:bans:index'))
         response = self.client.get(reverse('misago:admin:users:bans:index'))

+ 1 - 1
misago/users/tests/test_captcha_api.py

@@ -7,7 +7,7 @@ from misago.conf import settings
 
 
 class AuthenticateAPITests(TestCase):
 class AuthenticateAPITests(TestCase):
     def setUp(self):
     def setUp(self):
-        self.api_link = reverse('misago:api:captcha_question')
+        self.api_link = reverse('misago:api:captcha-question')
 
 
     def tearDown(self):
     def tearDown(self):
         settings.reset_settings()
         settings.reset_settings()

+ 4 - 4
misago/users/tests/test_decorators.py

@@ -7,14 +7,14 @@ from misago.users.testutils import UserTestCase
 class DenyAuthenticatedTests(UserTestCase):
 class DenyAuthenticatedTests(UserTestCase):
     def test_success(self):
     def test_success(self):
         """deny_authenticated decorator allowed guest request"""
         """deny_authenticated decorator allowed guest request"""
-        response = self.client.post(reverse('misago:request_activation'))
+        response = self.client.post(reverse('misago:request-activation'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
     def test_fail(self):
     def test_fail(self):
         """deny_authenticated decorator denied authenticated request"""
         """deny_authenticated decorator denied authenticated request"""
         self.login_user(self.get_authenticated_user())
         self.login_user(self.get_authenticated_user())
 
 
-        response = self.client.post(reverse('misago:request_activation'))
+        response = self.client.post(reverse('misago:request-activation'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
 
 
 
 
@@ -40,7 +40,7 @@ class DenyBannedIPTests(UserTestCase):
             banned_value='83.*',
             banned_value='83.*',
             user_message='Ya got banned!')
             user_message='Ya got banned!')
 
 
-        response = self.client.post(reverse('misago:request_activation'))
+        response = self.client.post(reverse('misago:request-activation'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
     def test_fail(self):
     def test_fail(self):
@@ -50,6 +50,6 @@ class DenyBannedIPTests(UserTestCase):
             banned_value='127.*',
             banned_value='127.*',
             user_message='Ya got banned!')
             user_message='Ya got banned!')
 
 
-        response = self.client.post(reverse('misago:request_activation'))
+        response = self.client.post(reverse('misago:request-activation'))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn('<p>Ya got banned!</p>', response.content)
         self.assertIn('<p>Ya got banned!</p>', response.content)

+ 23 - 13
misago/users/tests/test_forgottenpassword_views.py

@@ -9,14 +9,14 @@ from misago.users.tokens import make_password_change_token
 class ForgottenPasswordViewsTests(UserTestCase):
 class ForgottenPasswordViewsTests(UserTestCase):
     def test_guest_request_view_returns_200(self):
     def test_guest_request_view_returns_200(self):
         """request new password view returns 200 for guests"""
         """request new password view returns 200 for guests"""
-        response = self.client.get(reverse('misago:forgotten_password'))
+        response = self.client.get(reverse('misago:forgotten-password'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
     def test_authenticated_request_view_returns_200(self):
     def test_authenticated_request_view_returns_200(self):
         """request new password view returns 200 for authenticated"""
         """request new password view returns 200 for authenticated"""
         self.login_user(self.get_authenticated_user())
         self.login_user(self.get_authenticated_user())
 
 
-        response = self.client.get(reverse('misago:forgotten_password'))
+        response = self.client.get(reverse('misago:forgotten-password'))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
     def test_change_password_on_banned(self):
     def test_change_password_on_banned(self):
@@ -24,15 +24,19 @@ class ForgottenPasswordViewsTests(UserTestCase):
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'Pass.123')
 
 
-        Ban.objects.create(check_type=BAN_USERNAME,
-                           banned_value='bob',
-                           user_message='Nope!')
+        Ban.objects.create(
+            check_type=BAN_USERNAME,
+            banned_value='bob',
+            user_message='Nope!',
+        )
 
 
         password_token = make_password_change_token(test_user)
         password_token = make_password_change_token(test_user)
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:forgotten_password_change_form',
-                    kwargs={'user_id': test_user.pk, 'token': password_token}))
+            reverse('misago:forgotten-password-change-form', kwargs={
+                'pk': test_user.pk,
+                'token': password_token,
+            }))
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
         self.assertIn('<p>Nope!</p>', response.content)
         self.assertIn('<p>Nope!</p>', response.content)
 
 
@@ -46,8 +50,10 @@ class ForgottenPasswordViewsTests(UserTestCase):
         self.login_user(self.get_authenticated_user())
         self.login_user(self.get_authenticated_user())
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:forgotten_password_change_form',
-                    kwargs={'user_id': test_user.pk, 'token': password_token}))
+            reverse('misago:forgotten-password-change-form', kwargs={
+                'pk': test_user.pk,
+                'token': password_token,
+            }))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
         self.assertIn('your link has expired', response.content)
         self.assertIn('your link has expired', response.content)
 
 
@@ -59,8 +65,10 @@ class ForgottenPasswordViewsTests(UserTestCase):
         password_token = make_password_change_token(test_user)
         password_token = make_password_change_token(test_user)
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:forgotten_password_change_form',
-                    kwargs={'user_id': test_user.pk, 'token': 'abcdfghqsads'}))
+            reverse('misago:forgotten-password-change-form', kwargs={
+                'pk': test_user.pk,
+                'token': 'abcdfghqsads',
+            }))
         self.assertEqual(response.status_code, 400)
         self.assertEqual(response.status_code, 400)
         self.assertIn('your link is invalid', response.content)
         self.assertIn('your link is invalid', response.content)
 
 
@@ -72,7 +80,9 @@ class ForgottenPasswordViewsTests(UserTestCase):
         password_token = make_password_change_token(test_user)
         password_token = make_password_change_token(test_user)
 
 
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:forgotten_password_change_form',
-                    kwargs={'user_id': test_user.pk, 'token': password_token}))
+            reverse('misago:forgotten-password-change-form', kwargs={
+                'pk': test_user.pk,
+                'token': password_token,
+            }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(password_token, response.content)
         self.assertIn(password_token, response.content)

+ 5 - 6
misago/users/tests/test_lists_views.py

@@ -30,13 +30,13 @@ class UsersListLanderTests(UsersListTestCase):
         response = self.client.get(reverse('misago:users'))
         response = self.client.get(reverse('misago:users'))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
         self.assertTrue(response['location'].endswith(
         self.assertTrue(response['location'].endswith(
-                        reverse('misago:users_active_posters')))
+                        reverse('misago:users-active-posters')))
 
 
 
 
 class ActivePostersTests(UsersListTestCase):
 class ActivePostersTests(UsersListTestCase):
     def test_active_posters_list(self):
     def test_active_posters_list(self):
         """active posters page has no showstoppers"""
         """active posters page has no showstoppers"""
-        view_link = reverse('misago:users_active_posters')
+        view_link = reverse('misago:users-active-posters')
 
 
         response = self.client.get(view_link)
         response = self.client.get(view_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -44,8 +44,8 @@ class ActivePostersTests(UsersListTestCase):
         # Create 200 test users and see if errors appeared
         # Create 200 test users and see if errors appeared
         User = get_user_model()
         User = get_user_model()
         for i in xrange(200):
         for i in xrange(200):
-            User.objects.create_user('Bob%s' % i, 'm%s@te.com' % i, 'Pass.123',
-                                     posts=12345)
+            User.objects.create_user(
+                'Bob%s' % i, 'm%s@te.com' % i, 'Pass.123', posts=12345)
 
 
         response = self.client.get(view_link)
         response = self.client.get(view_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -55,8 +55,7 @@ class UsersRankTests(UsersListTestCase):
     def test_ranks(self):
     def test_ranks(self):
         """ranks lists are handled correctly"""
         """ranks lists are handled correctly"""
         for rank in Rank.objects.iterator():
         for rank in Rank.objects.iterator():
-            rank_link = reverse('misago:users_rank',
-                                kwargs={'rank_slug': rank.slug})
+            rank_link = reverse('misago:users-rank', kwargs={'slug': rank.slug})
             response = self.client.get(rank_link)
             response = self.client.get(rank_link)
 
 
             if rank.is_tab:
             if rank.is_tab:

+ 3 - 3
misago/users/tests/test_options_views.py

@@ -11,7 +11,7 @@ class OptionsViewsTests(AuthenticatedUserTestCase):
 
 
     def test_form_view_returns_200(self):
     def test_form_view_returns_200(self):
         """/options/some-form has no show stoppers"""
         """/options/some-form has no show stoppers"""
-        response = self.client.get(reverse('misago:options_form', kwargs={
+        response = self.client.get(reverse('misago:options-form', kwargs={
             'form_name': 'some-fake-form'
             'form_name': 'some-fake-form'
         }))
         }))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -36,7 +36,7 @@ class ConfirmChangeEmailTests(AuthenticatedUserTestCase):
     def test_invalid_token(self):
     def test_invalid_token(self):
         """invalid token is rejected"""
         """invalid token is rejected"""
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:options_confirm_email_change', kwargs={
+            reverse('misago:options-confirm-email-change', kwargs={
                 'token': 'invalid'
                 'token': 'invalid'
             }))
             }))
 
 
@@ -73,7 +73,7 @@ class ConfirmChangePasswordTests(AuthenticatedUserTestCase):
     def test_invalid_token(self):
     def test_invalid_token(self):
         """invalid token is rejected"""
         """invalid token is rejected"""
         response = self.client.get(
         response = self.client.get(
-            reverse('misago:options_confirm_password_change', kwargs={
+            reverse('misago:options-confirm-password-change', kwargs={
                 'token': 'invalid'
                 'token': 'invalid'
             }))
             }))
 
 

+ 16 - 16
misago/users/tests/test_profile_views.py

@@ -11,21 +11,21 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
     def setUp(self):
     def setUp(self):
         super(UserProfileViewsTests, self).setUp()
         super(UserProfileViewsTests, self).setUp()
         self.link_kwargs = {
         self.link_kwargs = {
-            'user_slug': self.user.slug,
-            'user_id': self.user.pk
+            'slug': self.user.slug,
+            'pk': self.user.pk
         }
         }
 
 
     def test_outdated_slugs(self):
     def test_outdated_slugs(self):
         """user profile view redirects to valid slig"""
         """user profile view redirects to valid slig"""
-        invalid_kwargs = {'user_slug': 'baww', 'user_id': self.user.pk}
-        response = self.client.get(reverse('misago:user_posts',
+        invalid_kwargs = {'slug': 'baww', 'pk': self.user.pk}
+        response = self.client.get(reverse('misago:user-posts',
                                            kwargs=invalid_kwargs))
                                            kwargs=invalid_kwargs))
 
 
         self.assertEqual(response.status_code, 301)
         self.assertEqual(response.status_code, 301)
 
 
     def test_user_posts_list(self):
     def test_user_posts_list(self):
         """user profile posts list has no showstoppers"""
         """user profile posts list has no showstoppers"""
-        response = self.client.get(reverse('misago:user_posts',
+        response = self.client.get(reverse('misago:user-posts',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -33,7 +33,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
 
     def test_user_threads_list(self):
     def test_user_threads_list(self):
         """user profile threads list has no showstoppers"""
         """user profile threads list has no showstoppers"""
-        response = self.client.get(reverse('misago:user_threads',
+        response = self.client.get(reverse('misago:user-threads',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -43,7 +43,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         """user profile followers list has no showstoppers"""
         """user profile followers list has no showstoppers"""
         User = get_user_model()
         User = get_user_model()
 
 
-        response = self.client.get(reverse('misago:user_followers',
+        response = self.client.get(reverse('misago:user-followers',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -55,7 +55,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
             followers.append(User.objects.create_user(*user_data))
             followers.append(User.objects.create_user(*user_data))
             self.user.followed_by.add(followers[-1])
             self.user.followed_by.add(followers[-1])
 
 
-        response = self.client.get(reverse('misago:user_followers',
+        response = self.client.get(reverse('misago:user-followers',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         for i in xrange(10):
         for i in xrange(10):
@@ -65,7 +65,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         """user profile follows list has no showstoppers"""
         """user profile follows list has no showstoppers"""
         User = get_user_model()
         User = get_user_model()
 
 
-        response = self.client.get(reverse('misago:user_follows',
+        response = self.client.get(reverse('misago:user-follows',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
 
 
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -77,7 +77,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
             followers.append(User.objects.create_user(*user_data))
             followers.append(User.objects.create_user(*user_data))
             followers[-1].followed_by.add(self.user)
             followers[-1].followed_by.add(self.user)
 
 
-        response = self.client.get(reverse('misago:user_follows',
+        response = self.client.get(reverse('misago:user-follows',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         for i in xrange(10):
         for i in xrange(10):
@@ -85,7 +85,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
 
     def test_username_history_list(self):
     def test_username_history_list(self):
         """user name changes history list has no showstoppers"""
         """user name changes history list has no showstoppers"""
-        response = self.client.get(reverse('misago:username_history',
+        response = self.client.get(reverse('misago:username-history',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('Your username was never changed.', response.content)
         self.assertIn('Your username was never changed.', response.content)
@@ -95,7 +95,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
         self.user.set_username('TestUser')
         self.user.set_username('TestUser')
         self.user.save()
         self.user.save()
 
 
-        response = self.client.get(reverse('misago:username_history',
+        response = self.client.get(reverse('misago:username-history',
                                            kwargs=self.link_kwargs))
                                            kwargs=self.link_kwargs))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn("TestUser", response.content)
         self.assertIn("TestUser", response.content)
@@ -109,9 +109,9 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
 
 
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user("Bob", "bob@bob.com", 'pass.123')
         test_user = User.objects.create_user("Bob", "bob@bob.com", 'pass.123')
-        link_kwargs = {'user_slug': test_user.slug, 'user_id': test_user.pk}
+        link_kwargs = {'slug': test_user.slug, 'pk': test_user.pk}
 
 
-        response = self.client.get(reverse('misago:user_ban',
+        response = self.client.get(reverse('misago:user-ban',
                                            kwargs=link_kwargs))
                                            kwargs=link_kwargs))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
@@ -119,7 +119,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
             'can_see_ban_details': 1,
             'can_see_ban_details': 1,
         })
         })
 
 
-        response = self.client.get(reverse('misago:user_ban',
+        response = self.client.get(reverse('misago:user-ban',
                                            kwargs=link_kwargs))
                                            kwargs=link_kwargs))
         self.assertEqual(response.status_code, 404)
         self.assertEqual(response.status_code, 404)
 
 
@@ -133,7 +133,7 @@ class UserProfileViewsTests(AuthenticatedUserTestCase):
                            staff_message="Staff m3ss4ge.",
                            staff_message="Staff m3ss4ge.",
                            is_checked=True)
                            is_checked=True)
 
 
-        response = self.client.get(reverse('misago:user_ban',
+        response = self.client.get(reverse('misago:user-ban',
                                            kwargs=link_kwargs))
                                            kwargs=link_kwargs))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn('User m3ss4ge', response.content)
         self.assertIn('User m3ss4ge', response.content)

+ 9 - 9
misago/users/tests/test_rankadmin_views.py

@@ -75,14 +75,14 @@ class RankAdminViewsTests(AdminTestCase):
 
 
         response = self.client.get(
         response = self.client.get(
             reverse('misago:admin:users:ranks:edit',
             reverse('misago:admin:users:ranks:edit',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(test_rank.name, response.content)
         self.assertIn(test_rank.name, response.content)
         self.assertIn(test_rank.title, response.content)
         self.assertIn(test_rank.title, response.content)
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:edit',
             reverse('misago:admin:users:ranks:edit',
-                    kwargs={'rank_id': test_rank.pk}),
+                    kwargs={'pk': test_rank.pk}),
             data={
             data={
                 'name': 'Top Lel',
                 'name': 'Top Lel',
                 'roles': [test_role_b.pk],
                 'roles': [test_role_b.pk],
@@ -116,7 +116,7 @@ class RankAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:default',
             reverse('misago:admin:users:ranks:default',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         test_rank = Rank.objects.get(slug='test-rank')
         test_rank = Rank.objects.get(slug='test-rank')
@@ -138,7 +138,7 @@ class RankAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:up',
             reverse('misago:admin:users:ranks:up',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         changed_rank = Rank.objects.get(slug='test-rank')
         changed_rank = Rank.objects.get(slug='test-rank')
@@ -161,11 +161,11 @@ class RankAdminViewsTests(AdminTestCase):
         # Move rank up
         # Move rank up
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:up',
             reverse('misago:admin:users:ranks:up',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:down',
             reverse('misago:admin:users:ranks:down',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         # Test move down
         # Test move down
@@ -187,7 +187,7 @@ class RankAdminViewsTests(AdminTestCase):
         test_rank = Rank.objects.get(slug='test-rank')
         test_rank = Rank.objects.get(slug='test-rank')
 
 
         response = self.client.get(reverse('misago:admin:users:ranks:users',
         response = self.client.get(reverse('misago:admin:users:ranks:users',
-                                           kwargs={'rank_id': test_rank.pk}))
+                                           kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
     def test_delete_view(self):
     def test_delete_view(self):
@@ -206,7 +206,7 @@ class RankAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:delete',
             reverse('misago:admin:users:ranks:delete',
-                    kwargs={'rank_id': test_rank.pk}))
+                    kwargs={'pk': test_rank.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:users:ranks:index'))
         self.client.get(reverse('misago:admin:users:ranks:index'))
@@ -249,7 +249,7 @@ class RankAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:ranks:edit',
             reverse('misago:admin:users:ranks:edit',
-                    kwargs={'rank_id': test_rank.pk}),
+                    kwargs={'pk': test_rank.pk}),
             data={
             data={
                 'name': 'Members',
                 'name': 'Members',
                 'roles': [test_role_a.pk],
                 'roles': [test_role_a.pk],

+ 6 - 6
misago/users/tests/test_rest_permissions.py

@@ -11,7 +11,7 @@ class UnbannedOnlyTests(UserTestCase):
     def test_api_allows_guests(self):
     def test_api_allows_guests(self):
         """policy allows guests"""
         """policy allows guests"""
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_password_form'), data={
+            reverse('misago:api:send-password-form'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -21,7 +21,7 @@ class UnbannedOnlyTests(UserTestCase):
         self.login_user(self.user)
         self.login_user(self.user)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_password_form'), data={
+            reverse('misago:api:send-password-form'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -34,7 +34,7 @@ class UnbannedOnlyTests(UserTestCase):
             user_message='Ya got banned!')
             user_message='Ya got banned!')
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_password_form'), data={
+            reverse('misago:api:send-password-form'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
@@ -50,7 +50,7 @@ class UnbannedAnonOnlyTests(UserTestCase):
         self.user.save()
         self.user.save()
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_activation'), data={
+            reverse('misago:api:send-activation'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -60,7 +60,7 @@ class UnbannedAnonOnlyTests(UserTestCase):
         self.login_user(self.user)
         self.login_user(self.user)
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_activation'), data={
+            reverse('misago:api:send-activation'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)
@@ -73,7 +73,7 @@ class UnbannedAnonOnlyTests(UserTestCase):
             user_message='Ya got banned!')
             user_message='Ya got banned!')
 
 
         response = self.client.post(
         response = self.client.post(
-            reverse('misago:api:send_activation'), data={
+            reverse('misago:api:send-activation'), data={
                 'email': self.user.email
                 'email': self.user.email
             })
             })
         self.assertEqual(response.status_code, 403)
         self.assertEqual(response.status_code, 403)

+ 4 - 4
misago/users/tests/test_user_avatar_api.py

@@ -130,11 +130,11 @@ class UserAvatarTests(AuthenticatedUserTestCase):
             self.assertTrue(avatar.isfile())
             self.assertTrue(avatar.isfile())
 
 
             tmp_avatar_kwargs = {
             tmp_avatar_kwargs = {
+                'pk': self.user.pk,
                 'secret': response_json['options']['crop_tmp']['secret'],
                 'secret': response_json['options']['crop_tmp']['secret'],
                 'hash': response_json['avatar_hash'],
                 'hash': response_json['avatar_hash'],
-                'user_id': self.user.pk
             }
             }
-            tmp_avatar_path = reverse('misago:user_avatar_source',
+            tmp_avatar_path = reverse('misago:user-avatar-source',
                                       kwargs=tmp_avatar_kwargs)
                                       kwargs=tmp_avatar_kwargs)
             response = self.client.get(tmp_avatar_path)
             response = self.client.get(tmp_avatar_path)
             self.assertEqual(response.status_code, 200)
             self.assertEqual(response.status_code, 200)
@@ -163,11 +163,11 @@ class UserAvatarTests(AuthenticatedUserTestCase):
             self.assertTrue(avatar.isfile())
             self.assertTrue(avatar.isfile())
 
 
             org_avatar_kwargs = {
             org_avatar_kwargs = {
+                'pk': self.user.pk,
                 'secret': response_json['options']['crop_org']['secret'],
                 'secret': response_json['options']['crop_org']['secret'],
                 'hash': response_json['avatar_hash'],
                 'hash': response_json['avatar_hash'],
-                'user_id': self.user.pk
             }
             }
-            org_avatar_path = reverse('misago:user_avatar_source',
+            org_avatar_path = reverse('misago:user-avatar-source',
                                       kwargs=tmp_avatar_kwargs)
                                       kwargs=tmp_avatar_kwargs)
             response = self.client.get(org_avatar_path)
             response = self.client.get(org_avatar_path)
             self.assertEqual(response.status_code, 200)
             self.assertEqual(response.status_code, 200)

+ 7 - 7
misago/users/tests/test_useradmin_views.py

@@ -187,7 +187,7 @@ class UserAdminViewsTests(AdminTestCase):
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         test_link = reverse('misago:admin:users:accounts:edit',
         test_link = reverse('misago:admin:users:accounts:edit',
-                            kwargs={'user_id': test_user.pk})
+                            kwargs={'pk': test_user.pk})
 
 
         response = self.client.get(test_link)
         response = self.client.get(test_link)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
@@ -219,8 +219,8 @@ class UserAdminViewsTests(AdminTestCase):
         """delete user threads view deletes threads"""
         """delete user threads view deletes threads"""
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
-        test_link = reverse('misago:admin:users:accounts:delete_threads',
-                            kwargs={'user_id': test_user.pk})
+        test_link = reverse('misago:admin:users:accounts:delete-threads',
+                            kwargs={'pk': test_user.pk})
 
 
         category = Category.objects.all_categories()[:1][0]
         category = Category.objects.all_categories()[:1][0]
         [post_thread(category, poster=test_user) for i in xrange(10)]
         [post_thread(category, poster=test_user) for i in xrange(10)]
@@ -243,8 +243,8 @@ class UserAdminViewsTests(AdminTestCase):
         """delete user posts view deletes posts"""
         """delete user posts view deletes posts"""
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
-        test_link = reverse('misago:admin:users:accounts:delete_posts',
-                            kwargs={'user_id': test_user.pk})
+        test_link = reverse('misago:admin:users:accounts:delete-posts',
+                            kwargs={'pk': test_user.pk})
 
 
         category = Category.objects.all_categories()[:1][0]
         category = Category.objects.all_categories()[:1][0]
         thread = post_thread(category)
         thread = post_thread(category)
@@ -268,8 +268,8 @@ class UserAdminViewsTests(AdminTestCase):
         """delete user account view deletes user account"""
         """delete user account view deletes user account"""
         User = get_user_model()
         User = get_user_model()
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
         test_user = User.objects.create_user('Bob', 'bob@test.com', 'pass123')
-        test_link = reverse('misago:admin:users:accounts:delete_account',
-                            kwargs={'user_id': test_user.pk})
+        test_link = reverse('misago:admin:users:accounts:delete-account',
+                            kwargs={'pk': test_user.pk})
 
 
         response = self.client.post(test_link, **self.ajax_header)
         response = self.client.post(test_link, **self.ajax_header)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)

+ 0 - 4
misago/users/tests/test_users_api.py

@@ -79,8 +79,6 @@ class FollowersListTests(AuthenticatedUserTestCase):
 
 
     def test_empty_list(self):
     def test_empty_list(self):
         """user without followers returns 200"""
         """user without followers returns 200"""
-        rank_slug = self.user.rank.slug
-
         response = self.client.get(self.link % self.user.pk)
         response = self.client.get(self.link % self.user.pk)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 
@@ -111,8 +109,6 @@ class FollowsListTests(AuthenticatedUserTestCase):
 
 
     def test_empty_list(self):
     def test_empty_list(self):
         """user without follows returns 200"""
         """user without follows returns 200"""
-        rank_slug = self.user.rank.slug
-
         response = self.client.get(self.link % self.user.pk)
         response = self.client.get(self.link % self.user.pk)
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
 
 

+ 5 - 5
misago/users/tests/test_warningadmin_views.py

@@ -59,13 +59,13 @@ class WarningsAdminViewsTests(AdminTestCase):
 
 
         response = self.client.get(
         response = self.client.get(
             reverse('misago:admin:users:warnings:edit',
             reverse('misago:admin:users:warnings:edit',
-                    kwargs={'warning_id': test_level.pk}))
+                    kwargs={'pk': test_level.pk}))
         self.assertEqual(response.status_code, 200)
         self.assertEqual(response.status_code, 200)
         self.assertIn(test_level.name, response.content)
         self.assertIn(test_level.name, response.content)
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:warnings:edit',
             reverse('misago:admin:users:warnings:edit',
-                    kwargs={'warning_id': test_level.pk}),
+                    kwargs={'pk': test_level.pk}),
             data={
             data={
                 'name': 'Edited Level',
                 'name': 'Edited Level',
                 'length_in_minutes': 5,
                 'length_in_minutes': 5,
@@ -105,7 +105,7 @@ class WarningsAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:warnings:up',
             reverse('misago:admin:users:warnings:up',
-                    kwargs={'warning_id': test_level_2.pk}))
+                    kwargs={'pk': test_level_2.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
         changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
@@ -137,7 +137,7 @@ class WarningsAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:warnings:down',
             reverse('misago:admin:users:warnings:down',
-                    kwargs={'warning_id': test_level_1.pk}))
+                    kwargs={'pk': test_level_1.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
         changed_level_1 = WarningLevel.objects.get(id=test_level_1.pk)
@@ -160,7 +160,7 @@ class WarningsAdminViewsTests(AdminTestCase):
 
 
         response = self.client.post(
         response = self.client.post(
             reverse('misago:admin:users:warnings:delete',
             reverse('misago:admin:users:warnings:delete',
-                    kwargs={'warning_id': test_level.pk}))
+                    kwargs={'pk': test_level.pk}))
         self.assertEqual(response.status_code, 302)
         self.assertEqual(response.status_code, 302)
 
 
         self.client.get(reverse('misago:admin:users:warnings:index'))
         self.client.get(reverse('misago:admin:users:warnings:index'))

+ 23 - 23
misago/users/urls/__init__.py

@@ -13,57 +13,57 @@ urlpatterns += patterns('misago.users.views.auth',
 
 
 
 
 urlpatterns += patterns('misago.users.views.activation',
 urlpatterns += patterns('misago.users.views.activation',
-    url(r'^request-activation/$', 'request_activation', name="request_activation"),
-    url(r'^activation/(?P<user_id>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'activate_by_token', name="activate_by_token"),
+    url(r'^request-activation/$', 'request_activation', name="request-activation"),
+    url(r'^activation/(?P<pk>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'activate_by_token', name="activate-by-token"),
 )
 )
 
 
 
 
 urlpatterns += patterns('misago.users.views.forgottenpassword',
 urlpatterns += patterns('misago.users.views.forgottenpassword',
-    url(r'^forgotten-password/$', 'request_reset', name='forgotten_password'),
-    url(r'^forgotten-password/(?P<user_id>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'reset_password_form', name='forgotten_password_change_form'),
+    url(r'^forgotten-password/$', 'request_reset', name='forgotten-password'),
+    url(r'^forgotten-password/(?P<pk>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'reset_password_form', name='forgotten-password-change-form'),
 )
 )
 
 
 
 
 urlpatterns += patterns('misago.users.views.options',
 urlpatterns += patterns('misago.users.views.options',
     url(r'^options/$', 'index', name='options'),
     url(r'^options/$', 'index', name='options'),
-    url(r'^options/(?P<form_name>[-a-zA-Z]+)/$', 'index', name='options_form'),
+    url(r'^options/(?P<form_name>[-a-zA-Z]+)/$', 'index', name='options-form'),
 
 
-    url(r'^options/forum-options/$', 'index', name='usercp_change_forum_options'),
-    url(r'^options/change-username/$', 'index', name='usercp_change_username'),
-    url(r'^options/sign-in-credentials/$', 'index', name='usercp_change_email_password'),
+    url(r'^options/forum-options/$', 'index', name='usercp-change-forum-options'),
+    url(r'^options/change-username/$', 'index', name='usercp-change-username'),
+    url(r'^options/sign-in-credentials/$', 'index', name='usercp-change-email-password'),
 
 
-    url(r'^options/change-email/(?P<token>[a-zA-Z0-9]+)/$', 'confirm_email_change', name='options_confirm_email_change'),
-    url(r'^options/change-password/(?P<token>[a-zA-Z0-9]+)/$', 'confirm_password_change', name='options_confirm_password_change'),
+    url(r'^options/change-email/(?P<token>[a-zA-Z0-9]+)/$', 'confirm_email_change', name='options-confirm-email-change'),
+    url(r'^options/change-password/(?P<token>[a-zA-Z0-9]+)/$', 'confirm_password_change', name='options-confirm-password-change'),
 )
 )
 
 
 
 
 urlpatterns += patterns('',
 urlpatterns += patterns('',
     url(r'^users/', include(patterns('misago.users.views.lists',
     url(r'^users/', include(patterns('misago.users.views.lists',
         url(r'^$', 'lander', name="users"),
         url(r'^$', 'lander', name="users"),
-        url(r'^active-posters/$', 'active_posters', name="users_active_posters"),
-        url(r'^(?P<rank_slug>[-a-zA-Z0-9]+)/$', 'rank', name="users_rank"),
-        url(r'^(?P<rank_slug>[-a-zA-Z0-9]+)/(?P<page>\d+)/$', 'rank', name="users_rank"),
+        url(r'^active-posters/$', 'active_posters', name="users-active-posters"),
+        url(r'^(?P<slug>[-a-zA-Z0-9]+)/$', 'rank', name="users-rank"),
+        url(r'^(?P<slug>[-a-zA-Z0-9]+)/(?P<page>\d+)/$', 'rank', name="users-rank"),
     )))
     )))
 )
 )
 
 
 
 
 urlpatterns += patterns('',
 urlpatterns += patterns('',
-    url(r'^user/(?P<user_slug>[a-zA-Z0-9]+)-(?P<user_id>\d+)/', include(patterns('misago.users.views.profile',
+    url(r'^user/(?P<slug>[a-zA-Z0-9]+)-(?P<pk>\d+)/', include(patterns('misago.users.views.profile',
         url(r'^$', 'lander', name="user"),
         url(r'^$', 'lander', name="user"),
-        url(r'^posts/$', 'posts', name="user_posts"),
-        url(r'^threads/$', 'threads', name="user_threads"),
-        url(r'^followers/$', 'followers', name="user_followers"),
-        url(r'^follows/$', 'follows', name="user_follows"),
-        url(r'^username-history/$', 'username_history', name="username_history"),
-        url(r'^ban-details/$', 'user_ban', name="user_ban"),
+        url(r'^posts/$', 'posts', name="user-posts"),
+        url(r'^threads/$', 'threads', name="user-threads"),
+        url(r'^followers/$', 'followers', name="user-followers"),
+        url(r'^follows/$', 'follows', name="user-follows"),
+        url(r'^username-history/$', 'username_history', name="username-history"),
+        url(r'^ban-details/$', 'user_ban', name="user-ban"),
     )))
     )))
 )
 )
 
 
 
 
 urlpatterns += patterns('',
 urlpatterns += patterns('',
     url(r'^user-avatar/', include(patterns('misago.users.views.avatarserver',
     url(r'^user-avatar/', include(patterns('misago.users.views.avatarserver',
-        url(r'^(?P<hash>[a-f0-9]+)/(?P<size>\d+)/(?P<user_id>\d+)\.png$', 'serve_user_avatar', name="user_avatar"),
-        url(r'^(?P<secret>[a-f0-9]+):(?P<hash>[a-f0-9]+)/(?P<user_id>\d+)\.png$', 'serve_user_avatar_source', name="user_avatar_source"),
-        url(r'^(?P<size>\d+)\.png$', 'serve_blank_avatar', name="blank_avatar"),
+        url(r'^(?P<hash>[a-f0-9]+)/(?P<size>\d+)/(?P<pk>\d+)\.png$', 'serve_user_avatar', name="user-avatar"),
+        url(r'^(?P<secret>[a-f0-9]+):(?P<hash>[a-f0-9]+)/(?P<pk>\d+)\.png$', 'serve_user_avatar_source', name="user-avatar-source"),
+        url(r'^(?P<size>\d+)\.png$', 'serve_blank_avatar', name="blank-avatar"),
     )))
     )))
 )
 )

+ 4 - 4
misago/users/urls/api.py

@@ -7,13 +7,13 @@ from misago.users.api.usernamechanges import UsernameChangesViewSet
 
 
 urlpatterns = patterns('misago.users.api.auth',
 urlpatterns = patterns('misago.users.api.auth',
     url(r'^auth/$', 'gateway', name='auth'),
     url(r'^auth/$', 'gateway', name='auth'),
-    url(r'^auth/send-activation/$', 'send_activation', name='send_activation'),
-    url(r'^auth/send-password-form/$', 'send_password_form', name='send_password_form'),
-    url(r'^auth/change-password/(?P<user_id>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'change_forgotten_password', name='change_forgotten_password'),
+    url(r'^auth/send-activation/$', 'send_activation', name='send-activation'),
+    url(r'^auth/send-password-form/$', 'send_password_form', name='send-password-form'),
+    url(r'^auth/change-password/(?P<pk>\d+)/(?P<token>[a-zA-Z0-9]+)/$', 'change_forgotten_password', name='change-forgotten-password'),
 )
 )
 
 
 urlpatterns += patterns('misago.users.api.captcha',
 urlpatterns += patterns('misago.users.api.captcha',
-    url(r'^captcha-question/$', 'question', name='captcha_question'),
+    url(r'^captcha-question/$', 'question', name='captcha-question'),
 )
 )
 
 
 router = MisagoApiRouter()
 router = MisagoApiRouter()

+ 3 - 3
misago/users/views/activation.py

@@ -24,7 +24,7 @@ def activation_view(f):
 @activation_view
 @activation_view
 def request_activation(request):
 def request_activation(request):
     request.frontend_context.update({
     request.frontend_context.update({
-        'SEND_ACTIVATION_API': reverse('misago:api:send_activation')
+        'SEND_ACTIVATION_API': reverse('misago:api:send-activation')
     })
     })
     return render(request, 'misago/activation/request.html')
     return render(request, 'misago/activation/request.html')
 
 
@@ -38,9 +38,9 @@ class ActivationError(Exception):
 
 
 
 
 @activation_view
 @activation_view
-def activate_by_token(request, user_id, token):
+def activate_by_token(request, pk, token):
     User = get_user_model()
     User = get_user_model()
-    inactive_user = get_object_or_404(User.objects, pk=user_id)
+    inactive_user = get_object_or_404(User.objects, pk=pk)
 
 
     try:
     try:
         if not inactive_user.requires_activation:
         if not inactive_user.requires_activation:

+ 4 - 4
misago/users/views/admin/users.py

@@ -31,7 +31,7 @@ class UserAdmin(generic.AdminBaseMixin):
 
 
     def create_form_type(self, request, target):
     def create_form_type(self, request, target):
         if request.user.is_superuser:
         if request.user.is_superuser:
-            add_staff_field = request.user.pk != target.id
+            add_staff_field = request.user.pk != target.pk
         else:
         else:
             add_staff_field = False
             add_staff_field = False
 
 
@@ -238,7 +238,8 @@ class NewUser(UserAdmin, generic.ModelFormView):
             title=form.cleaned_data['title'],
             title=form.cleaned_data['title'],
             rank=form.cleaned_data.get('rank'),
             rank=form.cleaned_data.get('rank'),
             joined_from_ip=request.user_ip,
             joined_from_ip=request.user_ip,
-            set_default_avatar=True)
+            set_default_avatar=True
+        )
 
 
         if form.cleaned_data.get('staff_level'):
         if form.cleaned_data.get('staff_level'):
             new_user.staff_level = form.cleaned_data['staff_level']
             new_user.staff_level = form.cleaned_data['staff_level']
@@ -251,8 +252,7 @@ class NewUser(UserAdmin, generic.ModelFormView):
 
 
         messages.success(
         messages.success(
             request, self.message_submit % {'user': target.username})
             request, self.message_submit % {'user': target.username})
-        return redirect('misago:admin:users:accounts:edit',
-                        user_id=new_user.id)
+        return redirect('misago:admin:users:accounts:edit', pk=new_user.pk)
 
 
 
 
 class EditUser(UserAdmin, generic.ModelFormView):
 class EditUser(UserAdmin, generic.ModelFormView):

+ 10 - 10
misago/users/views/avatarserver.py

@@ -21,12 +21,12 @@ def serve_blank_avatar(request, size):
 
 
 
 
 @cache_control(private=True, must_revalidate=False)
 @cache_control(private=True, must_revalidate=False)
-def serve_user_avatar(request, user_id, hash, size):
+def serve_user_avatar(request, pk, hash, size):
     size = clean_size(size)
     size = clean_size(size)
 
 
-    if int(user_id) > 0:
-        avatar_dir = store.get_avatars_dir_path(user_id)
-        avatar_file = get_user_avatar_file(user_id, size)
+    if int(pk) > 0:
+        avatar_dir = store.get_avatars_dir_path(pk)
+        avatar_file = get_user_avatar_file(pk, size)
         avatar_path = os.path.join(avatar_dir, avatar_file)
         avatar_path = os.path.join(avatar_dir, avatar_file)
 
 
         if Path(avatar_path).exists():
         if Path(avatar_path).exists():
@@ -39,13 +39,13 @@ def serve_user_avatar(request, user_id, hash, size):
 
 
 
 
 @never_cache
 @never_cache
-def serve_user_avatar_source(request, user_id, secret, hash):
+def serve_user_avatar_source(request, pk, secret, hash):
     fallback_avatar = get_blank_avatar_file(min(settings.MISAGO_AVATARS_SIZES))
     fallback_avatar = get_blank_avatar_file(min(settings.MISAGO_AVATARS_SIZES))
     User = get_user_model()
     User = get_user_model()
 
 
-    if user_id > 0:
+    if pk > 0:
         try:
         try:
-            user = User.objects.get(id=user_id)
+            user = User.objects.get(pk=pk)
 
 
             tokens = store.get_user_avatar_tokens(user)
             tokens = store.get_user_avatar_tokens(user)
             suffix = tokens.get(secret)
             suffix = tokens.get(secret)
@@ -61,7 +61,7 @@ def serve_user_avatar_source(request, user_id, secret, hash):
     if avatar_file == fallback_avatar:
     if avatar_file == fallback_avatar:
         avatar_dir = store.get_avatars_dir_path()
         avatar_dir = store.get_avatars_dir_path()
     else:
     else:
-        avatar_dir = store.get_avatars_dir_path(user_id)
+        avatar_dir = store.get_avatars_dir_path(pk)
 
 
     avatar_path = os.path.join(avatar_dir, avatar_file)
     avatar_path = os.path.join(avatar_dir, avatar_file)
     return make_file_response(avatar_path, 'image/png')
     return make_file_response(avatar_path, 'image/png')
@@ -78,8 +78,8 @@ def clean_size(size):
     return size
     return size
 
 
 
 
-def get_user_avatar_file(user_id, size):
-    return '%s_%s.png' % (user_id, size)
+def get_user_avatar_file(pk, size):
+    return '%s_%s.png' % (pk, size)
 
 
 
 
 def get_blank_avatar_file(size):
 def get_blank_avatar_file(size):

+ 5 - 5
misago/users/views/forgottenpassword.py

@@ -20,7 +20,7 @@ def reset_view(f):
 @reset_view
 @reset_view
 def request_reset(request):
 def request_reset(request):
     request.frontend_context.update({
     request.frontend_context.update({
-        'SEND_PASSWORD_RESET_API': reverse('misago:api:send_password_form'),
+        'SEND_PASSWORD_RESET_API': reverse('misago:api:send-password-form'),
     })
     })
     return render(request, 'misago/forgottenpassword/request.html')
     return render(request, 'misago/forgottenpassword/request.html')
 
 
@@ -30,9 +30,9 @@ class ResetError(Exception):
 
 
 
 
 @reset_view
 @reset_view
-def reset_password_form(request, user_id, token):
+def reset_password_form(request, pk, token):
     User = get_user_model()
     User = get_user_model()
-    requesting_user = get_object_or_404(User.objects, pk=user_id)
+    requesting_user = get_object_or_404(User.objects, pk=pk)
 
 
     try:
     try:
         if (request.user.is_authenticated() and
         if (request.user.is_authenticated() and
@@ -56,8 +56,8 @@ def reset_password_form(request, user_id, token):
                 'message': e.args[0],
                 'message': e.args[0],
             }, status=400)
             }, status=400)
 
 
-    api_url = reverse('misago:api:change_forgotten_password', kwargs={
-        'user_id': user_id,
+    api_url = reverse('misago:api:change-forgotten-password', kwargs={
+        'pk': pk,
         'token': token,
         'token': token,
     })
     })
 
 

+ 5 - 4
misago/users/views/lists.py

@@ -29,8 +29,9 @@ def render(request, template, context):
     for rank in Rank.objects.filter(is_tab=True).order_by('order'):
     for rank in Rank.objects.filter(is_tab=True).order_by('order'):
         context['pages'].append({
         context['pages'].append({
             'name': rank.name,
             'name': rank.name,
-            'reversed_link': reverse('misago:users_rank',
-                                     kwargs={'rank_slug': rank.slug}),
+            'reversed_link': reverse('misago:users-rank', kwargs={
+                'slug': rank.slug
+            }),
             'is_active': active_rank.pk == rank.pk if active_rank else None
             'is_active': active_rank.pk == rank.pk if active_rank else None
         })
         })
 
 
@@ -91,8 +92,8 @@ def active_posters(request):
 
 
 
 
 @allow_see_list
 @allow_see_list
-def rank(request, rank_slug, page=0):
-    rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=rank_slug)
+def rank(request, slug, page=0):
+    rank = get_object_or_404(Rank.objects.filter(is_tab=True), slug=slug)
     queryset = rank.user_set.select_related('rank').order_by('slug')
     queryset = rank.user_set.select_related('rank').order_by('slug')
 
 
     page = paginate(queryset, page, settings.MISAGO_USERS_PER_PAGE, 4)
     page = paginate(queryset, page, settings.MISAGO_USERS_PER_PAGE, 4)

+ 5 - 4
misago/users/views/profile.py

@@ -34,9 +34,9 @@ def profile_view(f):
 
 
         relations = ('rank', 'online_tracker', 'ban_cache')
         relations = ('rank', 'online_tracker', 'ban_cache')
         queryset = User.objects.select_related(*relations)
         queryset = User.objects.select_related(*relations)
-        profile = get_object_or_404(queryset, id=kwargs.pop('user_id'))
+        profile = get_object_or_404(queryset, pk=kwargs.pop('pk'))
 
 
-        validate_slug(profile, kwargs.pop('user_slug'))
+        validate_slug(profile, kwargs.pop('slug'))
         kwargs['profile'] = profile
         kwargs['profile'] = profile
 
 
         add_acl(request.user, profile)
         add_acl(request.user, profile)
@@ -108,8 +108,9 @@ def render(request, template, context):
 @profile_view
 @profile_view
 def lander(request, profile):
 def lander(request, profile):
     return redirect(user_profile.get_default_link(),
     return redirect(user_profile.get_default_link(),
-        user_slug=profile.slug,
-        user_id=profile.id)
+        slug=profile.slug,
+        pk=profile.pk,
+    )
 
 
 
 
 @profile_view
 @profile_view