2

I've got a Django app I've created which uses both Django Guardian to manage object-level permissions, and Django South to manage migrations. I've created a model mixin which allows models to define object-level permissions to be assigned as they are created, using a custom Meta attribute. So for example a Message model might look like:

class Message(AutoUserPermissionsMixin, models.Model):
  sender = models.ForeignKey(User)
  recipient = models.ForeignKey(User)
  text = models.TextField(blank=True)

  class Meta:
    permissions = (
      ('view_message', 'Can view message'),
      ('respond_to_message', 'Can respond to message'),
    )

    user_permissions_to_add = {
      'recipient' : ('view_message', 'respond_to_message',),
      'sender' : ('view_message',)
    }

The AutoUserPermissionsMixin defines a custom save() which reads the model's Meta to know which object-level permissions should be assigned to which field from user_permissions_to_add, and does the assignment. I added the custom Meta field by doing this in the top of file where I define AutoUserPermissionsMixin:

from django.db import models
models.options.DEFAULT_NAMES += ('user_permissions_to_add',)

The problem is, I'm trying to do a data migration in South to create a number of new model instances, and it doesn't assign the object-level permissions, because custom save() methods aren't handled in a migration.

Now I can use the same method being used in the custom save() to try and apply the permissions in the model, which is sync_object_permissions(instance, permissions). I want to read in the permissions at whatever state they are in on the Meta at the time of migration, not hard-code them into the migration. However, when trying to call sync_object_permissions(message_instance, permissions=message_instance._meta.user_permissions_to_add), South throws the error:

AttributeError: 'Options' object has no attribute 'user_permissions_to_add'

So for some reason, the Meta isn't being update with my custom user_permissions_to_add attribute at the time of migration. How can I make sure it's there on the Meta in the migration?

Greg Hinch
  • 807
  • 2
  • 8
  • 23

1 Answers1

1

South's modelinspector can be modified to slurp up your extra field on Meta so that this field is avilable during migrations.

Here's the code I've used (put this in your models.py file or some other file that it imports):

#make South record the Meta field "my_special_field" in its orm freezes
import south.modelsinspector as mi
mi.meta_details['my_special_field'] = ['my_special_field', {'default': None, 'ignore_missing': True}]

Note that if you do not include 'ignore_missing': True then South will throw an exception when it processes any models that do not include 'my_special_field' in their Meta options

You can inspect the other Meta fields that South already records by looking at the other fields on south.modelsinspector.meta_details

jcdude
  • 2,943
  • 2
  • 17
  • 14