Where do I create groups?

I need to create certain groups before users start using my app. I was thinking adding it to my models.py, but that creates a runtime warning about accessing the database while AppConfig.ready()/import modules (self.APPS_NOT_READY_WARNING_MSG). So, I’m thoughtfully confused about when is the right time to create groups. Do I need a setup process that creates them within a view? What happens when I need to add more groups? I really want to avoid downstream users creating groups, because the application is complicated as it is with certain permissions that only make sense in conjunction.

You’ve got at least four places I can think of off-hand where you could create groups. (Your choice among them depends upon how and when you need to do this.)

I presume that the same applies to custom permissions, or are those allowed to be on the codebase?

Correct. As a general rule, you don’t want to do any ORM-related work during Django startup.

I decided for the data migration path, since it can be part of the deployment without needing to specify extra steps:

I will have a migration like this:

def create_new_permissions_for_user(apps, schema_editor):
    ContentType = apps.get_model("contenttypes", "contenttype")
    user_type = ContentType.objects.get(app_label="auth", model="user")
    Permission = apps.get_model("auth", "Permission")

    Permission.objects.create(codename="view_self_user", name="Can view its own user", content_type=user_type)
    
    

class Migration(migrations.Migration):

    dependencies = [
        ("user_management", "0001_initial"),
        ("auth", "0012_alter_user_first_name_max_length"),
    ]

    operations = [migrations.RunPython(create_new_permissions_for_user)]

This seems “ok” considering that:

  1. I have no guarantee that anything exist in the order I say it would exists, therefore I need to add that “auth” dependency before everything else.
  2. There are two ways to access ContentType, I decided to not import directly the model from the system, but to leverage as much as possible how data migrations are supposed to be done. Is this unnecessary?

The dependency chain is transitive. If your user_management.0001_initial has a dependency on that auth.0012 migration, and your current migration depends upon user_management.0001, then you don’t need to add the auth.0012 as a dependency here.

For these models? Yes. The purpose of the apps.get_model is to protect this migration from the model-as-defined-in-models.py not matching the model-as-it-currently-exists-in-the-database situation that occurs when changes are being made to the models. In my opinion, it’s highly unlikely that either of these models are going to change in a way to invalidate this code.