I want some of my Django models to have an "owner" property. I may need to change or augment the logic later, and the logic is reused across many classes. So I'd like to just inherit from an Owned
class that lets me store the user who created the class. I'm not trying to populate the field yet, I just need it to exist.
First I tried this:
from django.db import models
from django.contrib.auth.models import User
class Owned(models.Model):
owner = models.ForeignKey(User, related_name='owner')
class Meta:
abstract = True
But when I inherited from Owned
in several subclasses, I got a Django reverse accessor error: Django Reverse Accessor Clashes
It looks like this "owner" property needs to have a different "related_name" in subclasses of the Owned
class.
So I tried this:
from django.db import models
from django.db.models.base import ModelBase
from django.contrib.auth.models import User
class _OwnedMeta(ModelBase):
'''
Should makes "Owned" class below work.
Gets around problem with reverse accessor clashes:
'''
def __init__(cls, name, bases, dct):
related_name = '{}_owner'.format(name)
dct['owner'] = models.ForeignKey(User, related_name=related_name)
super(_OwnedMeta, cls).__init__(name, bases, dct)
class Owned(models.Model):
'''
Instances get an "owner" attribute
that is a foreign key to '<class_name>_owner'
'''
__metaclass__ = _OwnedMeta
owner = models.ForeignKey(User, related_name='owner')
class Meta:
abstract = True
The idea is that when I subclass Owned
I'll get an owner
property with related name *class_name*_owner
.
Like this:
Class Subclass(Owned):
pass
instance = Subclass()
and now, if this worked, instance.subclassed would be a foreign key to the Django User
model and the related_name
would be "Subclass_owner."
But it doesn't work. This is an excerpt of the error message:
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/base.py", line 297, in add_to_class
value.contribute_to_class(cls, name)
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1588, in contribute_to_class
super(ForeignObject, self).contribute_to_class(cls, name, virtual_only=virtual_only)
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 272, in contribute_to_class
add_lazy_relation(cls, self, other, resolve_related_class)
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 84, in add_lazy_relation
operation(field, model, cls)
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 271, in resolve_related_class
field.do_related_class(model, cls)
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 307, in do_related_class
self.set_attributes_from_rel()
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 304, in set_attributes_from_rel
self.rel.set_field_name()
File "/Users/maxwellheiber/dev/dc/lib/python2.7/site-packages/django/db/models/fields/related.py", line 1259, in set_field_name
self.field_name = self.field_name or self.to._meta.pk.name
AttributeError: 'NoneType' object has no attribute 'name'
What am I doing wrong?