Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django 1.7 where to put the code to add Groups programmatically?

I have been trying to find the answer in the Django Auth docs, but can not seem to find what I am looking for.

The problem I am having is, when I define the code for adding Groups (same as Groups in the admin page):

#read_only
group, created = Group.objects.get_or_create(name='read_only')   
if created:
    group.permissions.add(can_read_campaign)
    logger.info('read_only_user Group created')
#standard
group, created = Group.objects.get_or_create(name='standard_user') 
if created:
    group.permissions.add(can_edit_users)
    logger.info('standard_user Group created')
#admin
group, created = Group.objects.get_or_create(name='admin_user') 
if created:
    group.permissions.add(can_edit_campaign, can_edit_users)
    logger.info('admin_user Group created')

When I have run this code in models.py and init.py and they both give me this error:

django.core.exceptions.AppRegistryNotReady

I presume this is due to the Model/init trying to insert things into the django app/admin too early?

How can I add these Groups programmatically?

EDIT:

This is not a duplicate question, this was actually adding permission and groups within the models during setup of the project, rather than through the shell.

I have solved this issues, by using signals and receivers (django modules).

I added the code to create the permissions/groups into it's own function and decorated this with a receiver (post_migrate), which will run this function after migrations are complete, removing this error.

@receiver(post_migrate)
def init_groups(sender, **kwargs):
    #permission and group code goes here
like image 681
adds68 Avatar asked Jul 29 '14 20:07

adds68


People also ask

How do you define groups in Django?

Django Admin Panel : In Admin Panel you will see Group in bold letter, Click on that and make 3-different group named level0, level1, level3 . Also, define the custom permissions according to the need. By Programmatically creating a group with permissions: Open python shell using python manage.py shell.

How to add user in Django?

The correct way to create a user in Django is to use the create_user function. This will handle the hashing of the password, etc..

Has permission in Django?

By default, Django automatically gives add, change, and delete permissions to all models, which allow users with the permissions to perform the associated actions via the admin site. You can define your own permissions to models and grant them to specific users.


3 Answers

I was recommended this way to do it:

Create a fake migration in the appropriate module:

python manage.py makemigrations --empty yourappname

Open up the file that was created, which should look like this:

# -*- coding: utf-8 -*-
from django.db import models, migrations

class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
    ]

And add your code:

# -*- coding: utf-8 -*-
from django.db import models, migrations

def add_group_permissions():
    #read_only
    group, created = Group.objects.get_or_create(name='read_only')   
    if created:
        group.permissions.add(can_read_campaign)
        logger.info('read_only_user Group created')

    #standard
    group, created = Group.objects.get_or_create(name='standard_user') 
    if created:
        group.permissions.add(can_edit_users)
        logger.info('standard_user Group created')

    #admin
    group, created = Group.objects.get_or_create(name='admin_user') 
    if created:
        group.permissions.add(can_edit_campaign, can_edit_users)
        logger.info('admin_user Group created')

class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(add_group_permissions),
    ]

Finally, run the migration:

python manage.py migrate

This is nice because you can deploy to Heroku or wherever and be sure it'll be applied, as it's just another migration.

like image 146
Rob Grant Avatar answered Oct 01 '22 11:10

Rob Grant


Combining @Robert Grant and this I was able to do it like:

python manage.py makemigrations --empty yourappname

And then:

from django.contrib.auth.models import Group, Permission
from django.db import models, migrations
import logging


logger = logging.getLogger(__name__)

campaign_group_permissions = {
  "Campaign Manager": [
    "add_campaign",
    "change_campaign",
    "delete_campaign",
    "view_campaign",
    "add_campaignsms",
    "add_sending",
    "change_sending",
    "view_sending"
  ]
}


def add_group_permissions():
    # See https://code.djangoproject.com/ticket/23422
    db_alias = schema_editor.connection.alias
    try:
        emit_post_migrate_signal(2, False, 'default')
    except TypeError:  # Django < 1.8
        emit_post_migrate_signal([], 2, False, 'default', db_alias)

    for group in campaign_group_permissions:
        role, created = Group.objects.get_or_create(name=group)
        logger.info(f'{group} Group created')
        for perm in campaign_group_permissions[group]:
            role.permissions.add(Permission.objects.get(codename=perm))
            logger.info(f'Permitting {group} to {perm}')
        role.save()


class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(add_group_permissions),
    ]

Note: this works on Django 3.x, but I'm pretty sure it will work for Django 1.7 as well.

like image 37
ruloweb Avatar answered Oct 01 '22 13:10

ruloweb


@Ruloweb's fantastic response almost worked for me, but I had to make a couple tweaks to get it to work in Django 3.1 with multiple apps.

First, I needed to add arguments to the add_group_permissions() function. I also needed to import the emit_post_migration_signal:

from django.contrib.auth.models import Group, Permission
from django.core.management.sql import emit_post_migrate_signal # <-- Added this
from django.db import models, migrations
import logging

logger = logging.getLogger(__name__)

public_group_permissions = {
  "Your permission group name here": ['your permissions here']
}

def add_group_permissions(apps, schema_editor): # <-- updated this

    # See https://code.djangoproject.com/ticket/23422
    db_alias = schema_editor.connection.alias

    try:
        emit_post_migrate_signal(2, False, 'default')
    except TypeError:  # Django < 1.8
        emit_post_migrate_signal([], 2, False, 'default', db_alias)

    for group in public_group_permissions:
        role, created = Group.objects.get_or_create(name=group)
        logger.info(f'{group} Group created')
        for perm in public_group_permissions[group]:
            role.permissions.add(Permission.objects.get(codename=perm))
            logger.info(f'Permitting {group} to {perm}')
        role.save()


class Migration(migrations.Migration):

    dependencies = [
        ('your_app_name', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(add_group_permissions),
    ]
like image 37
JSv4 Avatar answered Oct 01 '22 11:10

JSv4