Browse Source

Ranks and Roles apps refractored

Ralfp 12 years ago
parent
commit
124b3999a2

+ 19 - 18
misago/admin/layout/users.py

@@ -1,10 +1,11 @@
 from django.conf.urls import patterns, include, url
 from django.utils.translation import ugettext_lazy as _
 from misago.admin import AdminAction
-from misago.acl.models import Role
 from misago.banning.models import Ban
 from misago.newsletters.models import Newsletter
-from misago.users.models import User, Rank, Pruning
+from misago.ranks.models import Rank
+from misago.roles.models import Role
+from misago.users.models import User, Pruning
 
 ADMIN_ACTIONS=(
    AdminAction(
@@ -51,21 +52,21 @@ ADMIN_ACTIONS=(
                          'id': 'list',
                          'name': _("Browse Roles"),
                          'help': _("Browse all existing roles"),
-                         'route': 'admin_users_roles'
+                         'route': 'admin_roles'
                          },
                         {
                          'id': 'new',
                          'name': _("Add Role"),
                          'help': _("Create new role"),
-                         'route': 'admin_users_roles_new'
+                         'route': 'admin_roles_new'
                          },
                         ],
-               route='admin_users_roles',
-               urlpatterns=patterns('misago.users.admin.roles.views',
-                        url(r'^$', 'List', name='admin_users_roles'),
-                        url(r'^new/$', 'New', name='admin_users_roles_new'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_users_roles_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_users_roles_delete'),
+               route='admin_roles',
+               urlpatterns=patterns('misago.roles.views',
+                        url(r'^$', 'List', name='admin_roles'),
+                        url(r'^new/$', 'New', name='admin_roles_new'),
+                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_roles_edit'),
+                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_roles_delete'),
                     ),
                ),
    AdminAction(
@@ -80,21 +81,21 @@ ADMIN_ACTIONS=(
                          'id': 'list',
                          'name': _("Browse Ranks"),
                          'help': _("Browse all existing ranks"),
-                         'route': 'admin_users_ranks'
+                         'route': 'admin_ranks'
                          },
                         {
                          'id': 'new',
                          'name': _("Add Rank"),
                          'help': _("Create new rank"),
-                         'route': 'admin_users_ranks_new'
+                         'route': 'admin_ranks_new'
                          },
                         ],
-               route='admin_users_ranks',
-               urlpatterns=patterns('misago.users.admin.ranks.views',
-                        url(r'^$', 'List', name='admin_users_ranks'),
-                        url(r'^new/$', 'New', name='admin_users_ranks_new'),
-                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_users_ranks_edit'),
-                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_users_ranks_delete'),
+               route='admin_ranks',
+               urlpatterns=patterns('misago.ranks.views',
+                        url(r'^$', 'List', name='admin_ranks'),
+                        url(r'^new/$', 'New', name='admin_ranks_new'),
+                        url(r'^edit/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Edit', name='admin_ranks_edit'),
+                        url(r'^delete/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Delete', name='admin_ranks_delete'),
                     ),
                ),
    AdminAction(

+ 1 - 1
misago/newsletters/forms.py

@@ -2,7 +2,7 @@ from django.core.validators import RegexValidator
 from django.utils.translation import ugettext_lazy as _
 from django import forms
 from misago.forms import Form, YesNoSwitch
-from misago.users.models import Rank
+from misago.ranks.models import Rank
 
 class NewsletterForm(Form):
     name = forms.CharField(max_length=255)

+ 1 - 1
misago/newsletters/models.py

@@ -9,7 +9,7 @@ class Newsletter(models.Model):
     content_html = models.TextField(null=True,blank=True)
     content_plain = models.TextField(null=True,blank=True)
     ignore_subscriptions = models.BooleanField(default=False)
-    ranks = models.ManyToManyField('users.Rank')
+    ranks = models.ManyToManyField('ranks.Rank')
     
     def generate_token(self):
         self.token = get_random_string(32)

+ 0 - 0
misago/acl/__init__.py → misago/ranks/__init__.py


+ 37 - 0
misago/ranks/fixtures.py

@@ -0,0 +1,37 @@
+from misago.ranks.models import Rank
+from misago.utils import ugettext_lazy as _
+from misago.utils import get_msgid
+
+def load_fixtures():
+    rank_staff = Rank(
+                      name=_("Forum Team").message,
+                      title=_("Forum Team").message,
+                      style='staff',
+                      special=True,
+                      order=0,
+                      as_tab=True,
+                      )
+    rank_lurker = Rank(
+                      name=_("Lurker").message,
+                      style='lurker',
+                      order=1,
+                      criteria="100%"
+                      )
+    rank_member = Rank(
+                      name=_("Member").message,
+                      order=2,
+                      criteria="75%"
+                      )
+    rank_active = Rank(
+                      name=_("Most Valueable Posters").message,
+                      title=_("MVP").message,
+                      style='active',
+                      order=3,
+                      criteria="5%",
+                      as_tab=True,
+                      )
+    
+    rank_staff.save(force_insert=True)
+    rank_lurker.save(force_insert=True)
+    rank_member.save(force_insert=True)
+    rank_active.save(force_insert=True)

+ 0 - 0
misago/users/admin/ranks/forms.py → misago/ranks/forms.py


+ 0 - 0
misago/users/admin/ranks/__init__.py → misago/ranks/management/__init__.py


+ 0 - 0
misago/users/admin/roles/__init__.py → misago/ranks/management/commands/__init__.py


+ 2 - 4
misago/users/management/commands/updateranking.py → misago/ranks/management/commands/updateranking.py

@@ -1,9 +1,7 @@
-from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
 from django.core.management.base import BaseCommand, CommandError
 from django.db.models import F
-from django.utils import timezone
-from optparse import make_option
-from misago.users.models import User, Rank
+from misago.ranks.models import Rank
+from misago.users.models import User
 
 class Command(BaseCommand):
     """

+ 89 - 0
misago/ranks/models.py

@@ -0,0 +1,89 @@
+from django.conf import settings
+from django.db import models, connection, transaction
+from django.utils.translation import ugettext_lazy as _
+
+class Rank(models.Model):
+    """
+    Misago User Rank
+    Ranks are ready style/title pairs that are assigned to users either by admin (special ranks) or as result of user activity.
+    """
+    name = models.CharField(max_length=255)
+    name_slug = models.CharField(max_length=255,null=True,blank=True)
+    description = models.TextField(null=True,blank=True)
+    style = models.CharField(max_length=255,null=True,blank=True)
+    title = models.CharField(max_length=255,null=True,blank=True)
+    special = models.BooleanField(default=False)
+    as_tab = models.BooleanField(default=False)
+    order = models.IntegerField(default=0)
+    criteria = models.CharField(max_length=255,null=True,blank=True)
+    
+    def __unicode__(self):
+        return unicode(_(self.name))
+    
+    def assign_rank(self, users=0, special_ranks=None):
+        if not self.criteria or self.special or users == 0:
+            # Rank cant be rolled in
+            return False
+        
+        if self.criteria == "0":
+            # Just update all fellows
+            User.objects.exclude(rank__in=special_ranks).update(rank=self)
+        else:
+            # Count number of users to update
+            if self.criteria[-1] == '%':
+                criteria = int(self.criteria[0:-1])
+                criteria = int(math.ceil(float(users / 100.0)* criteria))
+            else:
+                criteria = int(self.criteria)
+            
+            # Join special ranks
+            if special_ranks:
+                special_ranks = ','.join(special_ranks)
+            
+            # Run raw query
+            cursor = connection.cursor()
+            try:
+                # Postgresql
+                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2'
+                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql'):
+                    if special_ranks:
+                        cursor.execute('''UPDATE users_user
+                            FROM (
+                                SELECT id
+                                FROM users_user
+                                WHERE rank_id NOT IN (%s)
+                                ORDER BY score DESC LIMIT %s
+                                ) AS updateable
+                            SET rank_id=%s
+                            WHERE id = updateable.id
+                            RETURNING *''' % (self.id, special_ranks, criteria))
+                    else:
+                        cursor.execute('''UPDATE users_user
+                            FROM (
+                                SELECT id
+                                FROM users_user
+                                ORDER BY score DESC LIMIT %s
+                                ) AS updateable
+                            SET rank_id=%s
+                            WHERE id = updateable.id
+                            RETURNING *''', [self.id, criteria])
+                        
+                # MySQL, SQLite and Oracle
+                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.mysql'
+                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.sqlite3'
+                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.oracle'):
+                    if special_ranks:
+                        cursor.execute('''UPDATE users_user
+                            SET rank_id=%s
+                            WHERE rank_id NOT IN (%s)
+                            ORDER BY score DESC
+                            LIMIT %s''' % (self.id, special_ranks, criteria))
+                    else:
+                        cursor.execute('''UPDATE users_user
+                        SET rank_id=%s
+                        ORDER BY score DESC
+                        LIMIT %s''', [self.id, criteria])
+            except Exception as e:
+                print 'Error updating users ranking: %s' % e
+            transaction.commit_unless_managed()
+        return True

+ 12 - 12
misago/users/admin/ranks/views.py → misago/ranks/views.py

@@ -5,8 +5,8 @@ from misago.admin import site
 from misago.admin.widgets import *
 from misago.forms import Form
 from misago.utils import slugify
-from misago.users.admin.ranks.forms import RankForm
-from misago.users.models import Rank
+from misago.ranks.forms import RankForm
+from misago.ranks.models import Rank
 
 def reverse(route, target=None):
     if target:
@@ -50,34 +50,34 @@ class List(ListWidget):
         for item in page_items:
             item.order = cleaned_data['pos_' + str(item.pk)]
             item.save(force_update=True)
-        return Message(_('Ranks order has been changed'), 'success'), reverse('admin_users_ranks')
+        return Message(_('Ranks order has been changed'), 'success'), reverse('admin_ranks')
     
     def sort_items(self, request, page_items, sorting_method):
         return page_items.order_by('order')
     
     def get_item_actions(self, request, item):
         return (
-                self.action('pencil', _("Edit Rank"), reverse('admin_users_ranks_edit', item)),
-                self.action('remove', _("Delete Rank"), reverse('admin_users_ranks_delete', item), post=True, prompt=_("Are you sure you want to delete this rank?")),
+                self.action('pencil', _("Edit Rank"), reverse('admin_ranks_edit', item)),
+                self.action('remove', _("Delete Rank"), reverse('admin_ranks_delete', item), post=True, prompt=_("Are you sure you want to delete this rank?")),
                 )
 
     def action_delete(self, request, items, checked):
         Rank.objects.filter(id__in=checked).delete()
-        return Message(_('Selected ranks have been deleted successfully.'), 'success'), reverse('admin_users_ranks')
+        return Message(_('Selected ranks have been deleted successfully.'), 'success'), reverse('admin_ranks')
 
 
 class New(FormWidget):
     admin = site.get_action('ranks')
     id = 'new'
-    fallback = 'admin_users_ranks' 
+    fallback = 'admin_ranks' 
     form = RankForm
     submit_button = _("Save Rank")
         
     def get_new_url(self, request, model):
-        return reverse('admin_users_ranks')
+        return reverse('admin_ranks')
     
     def get_edit_url(self, request, model):
-        return reverse('admin_users_ranks_edit', model)
+        return reverse('admin_ranks_edit', model)
     
     def submit_form(self, request, form, target):
         position = 0
@@ -101,14 +101,14 @@ class Edit(FormWidget):
     admin = site.get_action('ranks')
     id = 'edit'
     name = _("Edit Rank")
-    fallback = 'admin_users_ranks'
+    fallback = 'admin_ranks'
     form = RankForm
     target_name = 'name'
     notfound_message = _('Requested Rank could not be found.')
     submit_fallback = True
     
     def get_url(self, request, model):
-        return reverse('admin_users_ranks_edit', model)
+        return reverse('admin_ranks_edit', model)
     
     def get_edit_url(self, request, model):
         return self.get_url(request, model)
@@ -140,7 +140,7 @@ class Edit(FormWidget):
 class Delete(ButtonWidget):
     admin = site.get_action('ranks')
     id = 'delete'
-    fallback = 'admin_users_ranks'
+    fallback = 'admin_ranks'
     notfound_message = _('Requested Rank could not be found.')
     
     def action(self, request, target):

+ 0 - 0
misago/roles/__init__.py


+ 1 - 1
misago/acl/fixtures.py → misago/roles/fixtures.py

@@ -1,4 +1,4 @@
-from misago.acl.models import Role
+from misago.roles.models import Role
 from misago.utils import ugettext_lazy as _
 from misago.utils import get_msgid
 

+ 1 - 2
misago/users/admin/roles/forms.py → misago/roles/forms.py

@@ -1,7 +1,6 @@
-from django.core.validators import RegexValidator
 from django.utils.translation import ugettext_lazy as _
 from django import forms
-from misago.forms import Form, YesNoSwitch
+from misago.forms import Form
 
 class RoleForm(Form):
     name = forms.CharField(max_length=255)

+ 0 - 0
misago/acl/middleware.py → misago/roles/middleware.py


+ 0 - 0
misago/acl/models.py → misago/roles/models.py


+ 17 - 19
misago/users/admin/roles/views.py → misago/roles/views.py

@@ -1,12 +1,10 @@
 from django.core.urlresolvers import reverse as django_reverse
-from django import forms
 from django.utils.translation import ugettext as _
 from misago.admin import site
 from misago.admin.widgets import *
-from misago.forms import Form
 from misago.utils import slugify
-from misago.users.admin.roles.forms import RoleForm
-from misago.acl.models import Role
+from misago.roles.forms import RoleForm
+from misago.roles.models import Role
 
 def reverse(route, target=None):
     if target:
@@ -33,36 +31,36 @@ class List(ListWidget):
     
     def get_item_actions(self, request, item):
         return (
-                self.action('pencil', _("Edit Role"), reverse('admin_users_roles_edit', item)),
-                self.action('remove', _("Delete Role"), reverse('admin_users_roles_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
+                self.action('pencil', _("Edit Role"), reverse('admin_roles_edit', item)),
+                self.action('remove', _("Delete Role"), reverse('admin_roles_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
                 )
 
     def action_delete(self, request, items, checked):
         for item in items:
             if unicode(item.pk) in checked:
                 if item.token:
-                    return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
                 if item.protected and not request.user.is_god():
-                    return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_roles')
                 if item.user_set.count() > 0:
-                    return Message(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_users_roles')
+                    return Message(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_roles')
         
         Role.objects.filter(id__in=checked).delete()
-        return Message(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_users_roles')
+        return Message(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_roles')
 
 
 class New(FormWidget):
     admin = site.get_action('roles')
     id = 'new'
-    fallback = 'admin_users_roles' 
+    fallback = 'admin_roles' 
     form = RoleForm
     submit_button = _("Save Role")
         
     def get_new_url(self, request, model):
-        return reverse('admin_users_roles')
+        return reverse('admin_roles')
     
     def get_edit_url(self, request, model):
-        return reverse('admin_users_roles_edit', model)
+        return reverse('admin_roles_edit', model)
     
     def submit_form(self, request, form, target):
         new_role = Role(
@@ -76,14 +74,14 @@ class Edit(FormWidget):
     admin = site.get_action('roles')
     id = 'edit'
     name = _("Edit Role")
-    fallback = 'admin_users_roles'
+    fallback = 'admin_roles'
     form = RoleForm
     target_name = 'name'
     notfound_message = _('Requested Role could not be found.')
     submit_fallback = True
     
     def get_url(self, request, model):
-        return reverse('admin_users_roles_edit', model)
+        return reverse('admin_roles_edit', model)
     
     def get_edit_url(self, request, model):
         return self.get_url(request, model)
@@ -102,16 +100,16 @@ class Edit(FormWidget):
 class Delete(ButtonWidget):
     admin = site.get_action('roles')
     id = 'delete'
-    fallback = 'admin_users_roles'
+    fallback = 'admin_roles'
     notfound_message = _('Requested Role could not be found.')
     
     def action(self, request, target):
         if target.token:
-            return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_users_roles')
+            return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
         if target.protected and not request.user.is_god():
-            return Message(_('This role is protected.'), 'error'), reverse('admin_users_roles')
+            return Message(_('This role is protected.'), 'error'), reverse('admin_roles')
         if target.user_set.count() > 0:
-            return Message(_('This role is assigned to one or more usets.'), 'error'), reverse('admin_users_roles')
+            return Message(_('This role is assigned to one or more usets.'), 'error'), reverse('admin_roles')
 
         target.delete()
         return Message(_('Role "%(name)s" has been deleted.') % {'name': target.name}, 'success'), False

+ 4 - 3
misago/settings_base.py

@@ -79,7 +79,7 @@ MIDDLEWARE_CLASSES = (
     'misago.banning.middleware.BanningMiddleware',
     'misago.messages.middleware.MessagesMiddleware',
     'misago.users.middleware.UserMiddleware',
-    'misago.acl.middleware.ACLMiddleware',
+    'misago.roles.middleware.ACLMiddleware',
     'django.middleware.common.CommonMiddleware',
 )
 
@@ -99,7 +99,6 @@ INSTALLED_APPS = (
     'misago.monitor', # Forum statistics monitor
     'misago.utils', # Utility classes
     # Applications with dependencies
-    'misago.acl', # Web crawlers handling
     'misago.banning', # Banning and blacklisting users
     'misago.crawlers', # Web crawlers handling
     'misago.cookie_jar', # Cookies helper
@@ -113,7 +112,9 @@ INSTALLED_APPS = (
     'misago.stopwatch', # Simple stopwatch to measure time spent on request
     'misago.template', # Templates extensions
     'misago.themes', # Themes
-    'misago.users', # Users and groups
+    'misago.users', # Users
+    'misago.ranks', # User Ranks
+    'misago.roles', # User Roles
 )
 
 # IP's that can see debug toolbar

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

@@ -3,8 +3,9 @@ from django.core.exceptions import ValidationError
 from django.utils.translation import ugettext_lazy as _
 from django import forms
 from PIL import Image
-from misago.acl.models import Role
-from misago.users.models import User, Rank
+from misago.ranks.models import Rank
+from misago.roles.models import Role
+from misago.users.models import User
 from misago.users.validators import validate_password, validate_email
 from misago.forms import Form, YesNoSwitch
 

+ 0 - 34
misago/users/fixtures.py

@@ -1,6 +1,5 @@
 from misago.monitor.fixtures import load_monitor_fixture
 from misago.settings.fixtures import load_settings_fixture, update_settings_fixture
-from misago.users.models import Rank
 from misago.utils import ugettext_lazy as _
 from misago.utils import get_msgid
 
@@ -176,39 +175,6 @@ def load_fixtures():
     load_monitor_fixture(monitor_fixtures)
     load_settings_fixture(settings_fixtures)
     
-    rank_staff = Rank(
-                      name=_("Forum Team").message,
-                      title=_("Forum Team").message,
-                      style='staff',
-                      special=True,
-                      order=0,
-                      as_tab=True,
-                      )
-    rank_lurker = Rank(
-                      name=_("Lurker").message,
-                      style='lurker',
-                      order=1,
-                      criteria="100%"
-                      )
-    rank_member = Rank(
-                      name=_("Member").message,
-                      order=2,
-                      criteria="75%"
-                      )
-    rank_active = Rank(
-                      name=_("Most Valueable Posters").message,
-                      title=_("MVP").message,
-                      style='active',
-                      order=3,
-                      criteria="5%",
-                      as_tab=True,
-                      )
-    
-    rank_staff.save(force_insert=True)
-    rank_lurker.save(force_insert=True)
-    rank_member.save(force_insert=True)
-    rank_active.save(force_insert=True)
-    
     
 def update_fixtures():
     update_settings_fixture(settings_fixtures)

+ 1 - 1
misago/users/management/commands/adduser.py

@@ -2,7 +2,7 @@ from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
 from django.core.management.base import BaseCommand, CommandError
 from django.utils import timezone
 from optparse import make_option
-from misago.acl.models import Role
+from misago.roles.models import Role
 from misago.users.models import UserManager
 
 class Command(BaseCommand):

+ 5 - 91
misago/users/models.py

@@ -7,11 +7,10 @@ from django.contrib.auth.hashers import (
     check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
 from django.core.exceptions import ValidationError
 from django.core.mail import EmailMultiAlternatives
-from django.db import models, connection, transaction
+from django.db import models
 from django.template import RequestContext
 from django.utils import timezone as tz_util
 from django.utils.translation import ugettext_lazy as _
-from misago.acl.models import Role
 from misago.monitor.monitor import Monitor
 from misago.security import get_random_string
 from misago.settings.settings import Settings as DBSettings
@@ -52,6 +51,7 @@ class UserManager(models.Manager):
         
         # Get first rank
         try:
+            from misago.ranks.models import Rank
             default_rank = Rank.objects.filter(special=0).order_by('order')[0]
         except Rank.DoesNotExist:
             default_rank = None
@@ -76,6 +76,7 @@ class UserManager(models.Manager):
         
         # Set user roles?
         if not no_roles:
+            from misago.roles.models import Role
             new_user.roles.add(Role.objects.get(token='registered'))
             new_user.save(force_update=True)
         
@@ -145,7 +146,7 @@ class User(models.Model):
     followers = models.PositiveIntegerField(default=0)
     followers_delta = models.IntegerField(default=0)
     score = models.IntegerField(default=0,db_index=True)
-    rank = models.ForeignKey('Rank',null=True,blank=True,db_index=True,on_delete=models.SET_NULL)
+    rank = models.ForeignKey('ranks.Rank',null=True,blank=True,db_index=True,on_delete=models.SET_NULL)
     last_sync = models.DateTimeField(null=True,blank=True)
     follows = models.ManyToManyField('self',related_name='follows_set',symmetrical=False)
     ignores = models.ManyToManyField('self',related_name='ignores_set',symmetrical=False)
@@ -163,7 +164,7 @@ class User(models.Model):
     signature_ban_reason_user = models.TextField(null=True,blank=True)
     signature_ban_reason_admin = models.TextField(null=True,blank=True)
     timezone = models.CharField(max_length=255,default='utc')
-    roles = models.ManyToManyField(Role)
+    roles = models.ManyToManyField('roles.Role')
     acl_cache = models.TextField(null=True,blank=True)
     
     objects = UserManager()   
@@ -432,93 +433,6 @@ class Crawler(object):
     
     def is_crawler(self):
         return True
-    
-    
-class Rank(models.Model):
-    """
-    Misago User Rank
-    Ranks are ready style/title pairs that are assigned to users either by admin (special ranks) or as result of user activity.
-    """
-    name = models.CharField(max_length=255)
-    name_slug = models.CharField(max_length=255,null=True,blank=True)
-    description = models.TextField(null=True,blank=True)
-    style = models.CharField(max_length=255,null=True,blank=True)
-    title = models.CharField(max_length=255,null=True,blank=True)
-    special = models.BooleanField(default=False)
-    as_tab = models.BooleanField(default=False)
-    order = models.IntegerField(default=0)
-    criteria = models.CharField(max_length=255,null=True,blank=True)
-    
-    def __unicode__(self):
-        return unicode(_(self.name))
-    
-    def assign_rank(self, users=0, special_ranks=None):
-        if not self.criteria or self.special or users == 0:
-            # Rank cant be rolled in
-            return False
-        
-        if self.criteria == "0":
-            # Just update all fellows
-            User.objects.exclude(rank__in=special_ranks).update(rank=self)
-        else:
-            # Count number of users to update
-            if self.criteria[-1] == '%':
-                criteria = int(self.criteria[0:-1])
-                criteria = int(math.ceil(float(users / 100.0)* criteria))
-            else:
-                criteria = int(self.criteria)
-            
-            # Join special ranks
-            if special_ranks:
-                special_ranks = ','.join(special_ranks)
-            
-            # Run raw query
-            cursor = connection.cursor()
-            try:
-                # Postgresql
-                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql_psycopg2'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql'):
-                    if special_ranks:
-                        cursor.execute('''UPDATE users_user
-                            FROM (
-                                SELECT id
-                                FROM users_user
-                                WHERE rank_id NOT IN (%s)
-                                ORDER BY score DESC LIMIT %s
-                                ) AS updateable
-                            SET rank_id=%s
-                            WHERE id = updateable.id
-                            RETURNING *''' % (self.id, special_ranks, criteria))
-                    else:
-                        cursor.execute('''UPDATE users_user
-                            FROM (
-                                SELECT id
-                                FROM users_user
-                                ORDER BY score DESC LIMIT %s
-                                ) AS updateable
-                            SET rank_id=%s
-                            WHERE id = updateable.id
-                            RETURNING *''', [self.id, criteria])
-                        
-                # MySQL, SQLite and Oracle
-                if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.mysql'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.sqlite3'
-                    or settings.DATABASES['default']['ENGINE'] == 'django.db.backends.oracle'):
-                    if special_ranks:
-                        cursor.execute('''UPDATE users_user
-                            SET rank_id=%s
-                            WHERE rank_id NOT IN (%s)
-                            ORDER BY score DESC
-                            LIMIT %s''' % (self.id, special_ranks, criteria))
-                    else:
-                        cursor.execute('''UPDATE users_user
-                        SET rank_id=%s
-                        ORDER BY score DESC
-                        LIMIT %s''', [self.id, criteria])
-            except Exception as e:
-                print 'Error updating users ranking: %s' % e
-            transaction.commit_unless_managed()
-        return True
 
 
 class Pruning(models.Model):

+ 1 - 1
misago/users/views.py

@@ -1,7 +1,7 @@
 from django.core.urlresolvers import reverse
 from django.shortcuts import redirect
 from django.template import RequestContext
-from misago.users.models import User, Group
+from misago.users.models import User
 from misago.views import error403, error404
 
 

+ 2 - 1
misago/users/views/profiles.py

@@ -3,8 +3,9 @@ from django.shortcuts import redirect
 from django.template import RequestContext
 from misago.forms import FormFields
 from misago.messages import Message
+from misago.ranks.models import Rank
 from misago.users.forms import QuickFindUserForm
-from misago.users.models import User, Rank
+from misago.users.models import User
 from misago.views import error404
 from misago.utils import slugify
 

+ 0 - 0
templates/admin/users/ranks/list.html → templates/admin/ranks/list.html


+ 0 - 0
templates/admin/acl/admin_users_roles/list.html → templates/admin/roles/list.html