I'd like to define a proxy Model for Django's default User class, something kind of like this:
class MyUser(User):
def pretty_username(self):
if self.first_name:
return self.first_name
return self.username
class Meta:
proxy = True
And, I'd like to be able to call pretty_username from view code (and ideally, even from templates). Is there a simple way to take an instance of a standard User Model and type-cast it into an instance of MyUser?
Even some __init__
magic would be okay with me, as long as I can say:
my_user = MyUser(request.user)
in my view code.
The main Usage of a proxy model is to override the main functionality of existing Model. It is a type of model inheritance without creating a new table in Database. It always query on original model with overridden methods or managers.
Proxy model is a mathematically or statistically defined function that replicates or approximates the response of the full-scale simulation model output for selected input parameters (Denney 2010).
To create a new instance of a model, instantiate it like any other Python class: class Model (**kwargs) The keyword arguments are the names of the fields you've defined on your model. Note that instantiating a model in no way touches your database; for that, you need to save() .
Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client.
I think the actual answer to this question should be the comment by @fhahn in the other answer. And by changing class we can avoid the extra database call. Here is sample code:
My proxy model which change the representation from username
to email
if set:
class MyUser(User):
class Meta:
proxy = True
verbose_name = _('my user')
verbose_name_plural = _('my users')
def __str__(self):
return "%s" % (self.email or self.username)
class Wallet(models.Model):
owner = models.OneToOneField(MyUser, on_delete=models.PROTECT, related_name='wallet')
def __str__(self):
return "%s" % self.owner
A brief test in shell:
>>> from django.contrib.auth.models import User
>>> from my_apps.models import MyUser
>>> user = User.objects.get(pk=4)
>>> user
<User: AbKec6rumI9H9UmAC3Bh2kXUHzj4>
>>> user.email
'[email protected]'
>>> user.wallet
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'User' object has no attribute 'wallet'
>>> user.__class__ = MyUser
>>> user
<MyUser: [email protected]>
>>> user.wallet
<Wallet: [email protected]>
If you really want to have the full proxy object available, this is a quick and dirty solution (at the expense of an extra database call)
class MyUser(User):
def pretty_username(self):
if self.first_name:
return self.first_name
return self.username
class Meta:
proxy = True
def get_myuser(self):
try:
return MyUser.objects.get(pk=self.pk)
except MyUser.DoesNotExist:
return None
User.add_to_class('get_myuser', get_myuser)
So to use this in a view you could say:
request.user.get_myuser().pretty_username()
Or in a template:
{{ request.user.get_myuser.pretty_username }}
A nicer solution, if you're not tied to the proxy model idea, would be the following:
def pretty_username(self):
if self.first_name:
return self.first_name
return self.username
User.add_to_class('pretty_username', pretty_username)
This would allow the following:
request.user.pretty_username()
Or
{{ request.user.pretty_username }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With