I'm integrating an app which in the past has had a custom user model to replace auth.User
and added custom methods and relationships to other models.
I'd like to make it more of a reusable app, so I'm looking to add a proxy model to give the User
the same methods so that things like request.user.myfunc()
still work, and creating a OneToOneField
relationship to the User
for extra fields.
class ConsolesPermissionMixin(object):
@property
def is_admin(self):
return self.is_superuser or self.is_staff
_consoles = []
@property
def all_consoles(self):
if not self._consoles:
self._consoles = self.consoles.all()
return self._consoles
class ProxyUser(ConsolesPermissionMixin, User):
class Meta:
proxy = True
class ConsoleUser(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
participant = models.OneToOneField(
'consoles.Participant',
blank=True,
null=True
)
consoles = models.ManyToManyField(
'consoles.Console',
null=True,
blank=True,
)
objects = UserManager()
class Meta:
app_label = 'consoles'
verbose_name = _('Console User')
verbose_name_plural = _('Console Users')
So in order to implement this I've set AUTH_USER_MODEL = 'consoles.ProxyUser'
in settings. But this results in a TypeError: ProxyUser cannot proxy the swapped model 'consoles.ProxyUser'.
Surely for the proxy model to be used, it has to be set to AUTH_USER_MODEL
, but in turn does that mean that AUTH_USER_MODEL
can't be a proxy model?
Proxy models are used to modify Python behaviour of a model by extending a model class. Database tables aren't generated for proxy models. So you can't use a proxy model for AUTH_USER_MODEL
. In fact, you can't use a proxy model if you want a db table for that model.
To understand proxy models better, consider this:
class Badge(models.Model):
name = ...
color = ... # gold/silver
class GoldBadge(Badge)
class Meta:
proxy = True
def award(self, user):
# award a gold badge to user
class SilverBadge(Badge):
class Meta:
proxy = True
def award(self, user):
# award a silver badge to user
Tables are generated for only Badge
model whereas GoldBadge
and SilverBadge
are proxy models so no tables are generated for them. They are just extending the functionality (i.e. changing Python behaviour) of Badge
model.
See docs on proxy models