__init__.py 2.72 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
"""
Creates Levels for all installed apps that have levels.
"""
from django.db.models import get_models, signals
from django.db import DEFAULT_DB_ALIAS
from django.core.exceptions import ImproperlyConfigured

from ..models import Level, AclBase


def create_levels(app, created_models, verbosity, db=DEFAULT_DB_ALIAS,
                  **kwargs):
    """Create and set the weights of the configured Levels.

    Based on django.contrib.auth.management.__init__.create_permissions"""
    # if not router.allow_migrate(db, auth_app.Permission):
    #    return

    from django.contrib.contenttypes.models import ContentType

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

    # 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.
Bach Dániel committed
34 35
        ctype1 = ContentType.objects.db_manager(db).get_for_model(klass)
        ctypes.add(ctype1)
36 37 38
        weight = 0
        try:
            for codename, name in klass.ACL_LEVELS:
Bach Dániel committed
39 40
                searched_levels.append((ctype1, (codename, name)))
                level_weights.append((ctype1, codename, weight))
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
                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.
    all_levels = set(Level.objects.using(db).filter(
        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
    ]
    Level.objects.using(db).bulk_create(levels)
    if verbosity >= 2:
62
        print("Adding levels [%s]." % ", ".join(unicode(l) for l in levels))
Őry Máté committed
63
        print("Searched: [%s]." % ", ".join(
64 65
            unicode(l) for l in searched_levels))
        print("All: [%s]." % ", ".join(unicode(l) for l in all_levels))
66 67 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)


signals.post_syncdb.connect(
    create_levels, dispatch_uid="circle.acl.management.create_levels")