Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Clean permission table

During development apps and models permissions are sometimes removed or renamed. What's a good way to clean the leftovers from the permissions table without breaking something?

For example: I have an app articles with model Article with some permissions.

class Article(models.Model):
    title = ...
    text = ...

    class Meta:
        permissions = (
            ('can_edit_title', 'Can edit title of article'),
            ('can_edit_text', 'Can edit text of article'),
        )

I add this permission by command (with installed django_extension):

./manage update_permissions

But later I realise, that it would be better to name it can_update_title. So I change the model:

class Article(models.Model):
    ...

    class Meta:
        permissions = (
            ('can_update_title', 'Can update title of article'),
            ('can_update_text', 'Can update text of article'),
        )

When I update permissions there are both permissions in Django administration and it is really confusing for users - administrators.

like image 289
Tom Tichý Avatar asked Jul 25 '13 12:07

Tom Tichý


2 Answers

Short answer: register the Permission with the admin site. add this to your admin.py file:

from django.contrib.auth.models import Permission
admin.site.register(Permission)

Then you control everything from there.

Long answer: Permission are objects, just like everything else in django. They are saved into the database, and linked linked to users and groups through a ManyToMany relationship. When you simply changed the name of the permission in the Meta class of the Article model, django had no way of knowing that you still ment the same object as before, so instead it created a new one.

What you should've done was, after changing the name of the permission in the model was to also change the name of the correlating permission object in your database.

The easiest way to do this is to register the Permission object with the admin site, so you'd have control from there. You'd still need to change it in both places (models.py and your DB) for any name change, but the admin site makes this easier.

Keep in mind that the extra Permission object you created ('update') has a new pk, meaning that if you just delete your older Permission object ('edit') it would have consequences on anything it had a relation with. If you have data that you don't want to lose I suggest writing a script to merge the two Permission objects to avoid any errors

like image 126
yuvi Avatar answered Oct 22 '22 15:10

yuvi


A Django builtin management command exists that takes care of removing/deleting stale content types - and while deleting stale content types this command also deletes related permissions:

./manage.py remove_stale_contenttypes [--include-stale-apps]

It also takes an optional argument --include-stale-apps which results in:

"Deletes stale content types including ones from previously installed apps that have been removed from INSTALLED_APPS."

Quoted from the command help text. Official docs: https://docs.djangoproject.com/en/4.0/ref/django-admin/#remove-stale-contenttypes

This command lets the user confirm the hits (content types and permissions) and you also have the option to answer "No, don't do anything" each time; example:

./manage.py remove_stale_contenttypes --include-stale-apps
Some content types in your database are stale and can be deleted.
Any objects that depend on these content types will also be deleted.
The content types and dependent objects that would be deleted are:

    - Content type for core.affiliation
    - 4 auth.Permission object(s)
    ...

This list doesn't include any cascade deletions to data outside of Django's
models (uncommon).

Are you sure you want to delete these content types?
If you're unsure, answer 'no'.
Type 'yes' to continue, or 'no' to cancel: yes
Some content types in your database are stale and can be deleted.
Any objects that depend on these content types will also be deleted.
The content types and dependent objects that would be deleted are:

    - Content type for foo.bar
    - 3 auth.Permission object(s)
    - 3 auth.Group_permissions object(s)
    - Content type for foo.baz
    - 3 auth.Permission object(s)
    - 6 auth.Group_permissions object(s)
    ...

This list doesn't include any cascade deletions to data outside of Django's
models (uncommon).

Are you sure you want to delete these content types?
If you're unsure, answer 'no'.
Type 'yes' to continue, or 'no' to cancel: yes
Some content types in your database are stale and can be deleted.
Any objects that depend on these content types will also be deleted.
The content types and dependent objects that would be deleted are:

    - Content type for misc.whatever
    - 4 auth.Permission object(s)
    ...

This list doesn't include any cascade deletions to data outside of Django's
models (uncommon).

Are you sure you want to delete these content types?
If you're unsure, answer 'no'.
Type 'yes' to continue, or 'no' to cancel: yes
like image 36
tombreit Avatar answered Oct 22 '22 14:10

tombreit