__init__.py 2.78 KB
Newer Older
1 2 3
"""
Creates Levels for all installed apps that have levels.
"""
4 5
from django.db.models import signals
from django.apps import apps
6 7 8 9 10 11
from django.db import DEFAULT_DB_ALIAS
from django.core.exceptions import ImproperlyConfigured

from ..models import Level, AclBase


12
def create_levels(app_config, verbosity=False, using=DEFAULT_DB_ALIAS,
13 14 15 16
                  **kwargs):
    """Create and set the weights of the configured Levels.

    Based on django.contrib.auth.management.__init__.create_permissions"""
17
    # if not router.allow_migrate(using, auth_app.Permission):
18 19 20 21
    #    return

    from django.contrib.contenttypes.models import ContentType

22 23
    app_models = [k for k in apps.get_models(app_config)
                  if AclBase in k.__bases__]
Őry Máté committed
24 25
    print "Creating levels for models: %s." % ", ".join(
        [m.__name__ for m in app_models])
26 27 28 29 30 31 32 33 34 35

    # This will hold the levels we're looking for as
    # (content_type, (codename, name))
    searched_levels = list()
    level_weights = list()
    # The codenames and ctypes that should exist.
    ctypes = set()
    for klass in app_models:
        # Force looking up the content types in the current database
        # before creating foreign keys to them.
36
        ctype1 = ContentType.objects.db_manager(using).get_for_model(klass)
Bach Dániel committed
37
        ctypes.add(ctype1)
38 39 40
        weight = 0
        try:
            for codename, name in klass.ACL_LEVELS:
Bach Dániel committed
41 42
                searched_levels.append((ctype1, (codename, name)))
                level_weights.append((ctype1, codename, weight))
43 44 45 46 47 48 49 50
                weight += 1
        except AttributeError:
            raise ImproperlyConfigured(
                "Class %s doesn't have ACL_LEVELS attribute." % klass)

    # Find all the Levels that have a content_type for a model we're
    # looking for.  We don't need to check for codenames since we already have
    # a list of the ones we're going to create.
51
    all_levels = set(Level.objects.using(using).filter(
52 53 54 55 56 57 58 59 60 61
        content_type__in=ctypes,
    ).values_list(
        "content_type", "codename"
    ))

    levels = [
        Level(codename=codename, name=name, content_type=ctype)
        for ctype, (codename, name) in searched_levels
        if (ctype.pk, codename) not in all_levels
    ]
62
    Level.objects.using(using).bulk_create(levels)
63
    if verbosity >= 2:
64
        print("Adding levels [%s]." % ", ".join(unicode(l) for l in levels))
Őry Máté committed
65
        print("Searched: [%s]." % ", ".join(
66 67
            unicode(l) for l in searched_levels))
        print("All: [%s]." % ", ".join(unicode(l) for l in all_levels))
68 69 70 71 72 73 74

    # set weights
    for ctype, codename, weight in level_weights:
        Level.objects.filter(codename=codename,
                             content_type=ctype).update(weight=weight)


75
signals.post_migrate.connect(
76
    create_levels, dispatch_uid="circle.acl.management.create_levels")