9

Every now and then, you have the need to rename a model in Django (or, in one recent case I encountered, split one model into two, with new/different names). (Yes, proper planning helps to avoid this situation).

After renaming corresponding tables in the db and fixing affected code, one problem remains: Any permissions granted to Users or Groups to operate on those models still references the old model names. Is there any automated or semi-automated way to fix this, or is it just a matter of manual db surgery? (in development you can drop the auth_permissions table and syncdb to recreate it, but production isn't so simple).

shacker
  • 14,712
  • 8
  • 89
  • 89
  • 1
    9 years later ... do you remember how you ended up doing this? – Shadi May 15 '18 at 09:04
  • Hah, no I don't remember, sorry. Are other answers on this page helpful? Please post if you come up with a recipe that works for Django 2. – shacker May 15 '18 at 22:05
  • 1
    in my particular case, my django database was populated with an ETL script from a legacy database. I felt like fixing permissions would be followed up with fixing indices and postgresql sequences, etc., and I didn't want to go into the rabbit hole. I ended up clearing the database, re-running a django migrate with the new model names for a fresh database, and re-running the ETL script – Shadi May 16 '18 at 05:52

5 Answers5

2

If you happened to have used a South schema migration to rename the table, the following line in the forward migration would have done this automatically:

db.send_create_signal('appname', ['modelname'])
Jian
  • 10,320
  • 7
  • 38
  • 43
2

Here's a snippet that fills in missing contenttypes and permissions. I wonder if it could be extended to at least do some of the donkey work for cleaning up auth_permissions.

Andy Baker
  • 21,158
  • 12
  • 58
  • 71
  • Note this version of the script does not work with Django 1.0 - use http://www.djangosnippets.org/snippets/696/ instead. – shacker Sep 03 '09 at 13:30
0

I recently had this issue and wrote a function to solve it. You'll typically have a discrepancy with both the ContentType and Permission tables if you rename a model/table. Django has built-in helper functions to resolve the issue and you can use them as follow:

from django.contrib.auth.management import create_permissions
from django.contrib.contenttypes.management import update_all_contenttypes
from django.db.models import get_apps

def update_all_content_types_and_permissions():
    for app in get_apps():
        create_permissions(app, None, 2)
    update_all_contenttypes()
B Robster
  • 40,605
  • 21
  • 89
  • 122
  • does not work in my case (Django 1.7): `'module' object has no attribute 'models_module'` – linqu Mar 30 '15 at 16:15
0

I got about half-way through a long answer that detailed the plan of attack I would take in this situation, but as I was writing I realized there probably isn't any way around having to do a maintenance downtime in this situation.

You can minimize the downtime by having a prepared loaddata script of course, although care needs to be taken to make sure the auth_perms primary keys are in sync.

Also see short answer: no automated way to do this of which I'm aware.

Van Gale
  • 43,536
  • 9
  • 71
  • 81
0

I changed verbose names in my application, and in Django 2.2.7 this is the only way I found to fix permissions:

from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import Permission

class Command(BaseCommand):
    help = 'Fixes permissions names'

    def handle(self, *args, **options):
        for p in Permission.objects.filter(content_type__app_label="your_app_label_here"):
            p.name = "Can %s %s"%(p.codename.split('_')[0], p.content_type.model_class()._meta.verbose_name)
            p.save()
Elektordi
  • 355
  • 2
  • 8