I'm attempting to create an intermediate model, Permissions, between 'auth.Group' and any other custom models; this will serve as permissions or a means of what is visible to which groups.
I have been able to create an intermediate model, ExamplePermissions, between 'auth.Group' and one model.
class Example(TimeStampable, Ownable, Model):
groups = models.ManyToManyField('auth.Group', through='ExamplePermissions', related_name='examples')
name = models.CharField(max_length=255)
...
# Used for chaining/mixins
objects = ExampleQuerySet.as_manager()
def __str__(self):
return self.name
class ExamplePermissions(Model):
example = models.ForeignKey(Example, related_name='group_details')
group = models.ForeignKey('auth.Group', related_name='example_details')
write_access = models.BooleanField(default=False)
def __str__(self):
return ("{0}'s Example {1}").format(str(self.group), str(self.example))
However, the issue is that this opposes reusability. To create a model that allows any custom model to be associated with it, I implemented a GenericForeignKey in place of a ForeignKey as follows:
class Dumby(Model):
groups = models.ManyToManyField('auth.Group', through='core.Permissions', related_name='dumbies')
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Permissions(Model):
# Used to generically relate a model with the group model
content_type = models.ForeignKey(ContentType, related_name='group_details')
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
#
group = models.ForeignKey('auth.Group', related_name='content_details')
write_access = models.BooleanField(default=False)
def __str__(self):
return ("{0}'s Content {1}".format(str(self.group), str(self.content_object)))
Upon attempting to make migrations, it errors with:
core.Permissions: (fields.E336) The model is used as an intermediate model by 'simulations.Dumby.groups', but it does not have a foreign key to 'Dumby' or 'Group'.
At first glance, using a GenericForeignKey in an intermediate table seems like a dead end. If this is the case, is there some generally accepted way of handling such a situation besides the cumbersome and redundant approach of creating a custom intermediate model for each custom model?
Do not use ManyToManyField when using GenericForeignKey in your intermediate model; instead, use GenericRelation, so your groups field would be simply declared as:
groups = generic.GenericRelation(Permissions)
See reverse generic relations for more details.