2👍
The ForeignKey
from comments.Comment
is to django’s built-in User
object, so querying comment.user
will give you the parent object (ie: the base User
model). However, django inheritance does provide a way to get the subclass version from the superclass:
{{ comment.user.customeruser }}
Which would then allow you to do:
{{ comment.user.customeruser.customproperty }}
I happen to think this is a weakness in Django’s inheritance implementation since it doesn’t exactly mirror the behaviour you’d expect from object inheritance in Python generally, but at least there is a workaround. Since I’m hardly rushing out to submit a patch with my version of the right behaviour, I can’t complain 🙂
I agree with Carl Meyer’s comment: it could expensive to automatically fetch the subclass without altering the parent model’s db table, and returning the instance of the subclass from the parent class query would be inconsistent with Django’s promise that a queryset returns the model on which the queryset was run.
I still find in practice, however, that Django’s inheritance leads to some awkward extra steps on occasion. Having used Django since 0.91, and knowing that all the different strategies for resolving object-relational mapping issues have tradeoffs, I’m very happy to have inheritance in Django now, and feel that the current implementation is excellent… so I’d hate for my original answer to be construed as a slight against the project.
As such, I thought I would edit this answer to link to an answer Carl himself provided on a solution in cases where you don’t know what type the subclass is: How do I access the child classes of an object in Django without knowing the name of the child class?. He offers advice there for using the ContentType framework. Still some indirection involved, but a good, generalizable, option in the toolkit.
2👍
As you can see in the comments of that post, it is still controversially discussed, what is the best way.
I tried it by subclassing too, but I ran in many problems, while using profiles work perfectly for me.
class IRCUser(models.Model):
user = models.ForeignKey(User, unique=True)
name = models.CharField(max_length=100, blank= True, null = True )
friends = models.ManyToManyField("IRCUser", blank= True, null = True)
dataRecieved= models.BooleanField(default=False)
creating an IRCUser works like this:
>>> IRCUser(user = User.objects.get(username='Kermit')).save()
EDIT: Why are user_profiles elegant:
Let’s assume, we are writing a webapp, that will behave as a multi-protocol chat. The users can provide their accounts on ICQ, MSN, Jabber, FaceBook, Google Talk …..
We are free to create a custom user class by inheritance, that will hold all the additional informations.
class CustomUser(User):
irc_username = models.CharField(blank=True, null=True)
irc_password = models.PasswordField(blank=True, null=True)
msn_username = models.CharField(blank=True, null=True)
msn_password = models.PasswordField(blank=True, null=True)
fb_username = models.CharField(blank=True, null=True)
fb_password = models.PasswordField(blank=True, null=True)
gt_username = models.CharField(blank=True, null=True)
gt_password = models.PasswordField(blank=True, null=True)
....
....
this leads to
- data-rows with a lot of zero-values
- tricky what-if-then validation
- the impossibility, to have more the one account with the same service
So now let’s do it with user_profiles
class IRCProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='ircprofile')
username = models.CharField()
password = models.PasswordField()
class MSNProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='msnprofile')
username = models.CharField()
password = models.PasswordField()
class FBProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='fbprofile')
username = models.CharField()
password = models.PasswordField()
the result:
- User_profiles can be created when needed
- the db isn’t flooded by zero-values
- n profiles of same type can be assigned to one user
- validation is easy
this may lead to a more cryptic syntax in the templates, but we are free to have some shortcuts in our views/template_tags or to use {% with ... %}
to flavour it as we want.
- [Django]-Uwsgi segmentation fault for one specific route
- [Django]-Reverse for 'edit' with no arguments not found. 1 pattern(s) tried: ['articles/edit/(?P<pk>[0-9]+)/$']
- [Django]-Django Class Based view calling an other one
- [Django]-Is using the "escape" tag really mandatory as a good security pattern in Django?
- [Django]-Django filter, many queries in array
1👍
I don’t think there is a way around it, because as you said, comment.user
is a User
, not a CustomUser
.
See http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models:
QUERYSETS STILL RETURN THE MODEL THAT WAS REQUESTED
There is no way to have Django return, say, a MyUser object whenever you query for User objects. A queryset for User objects will return those types of objects. The whole point of proxy objects is that code relying on the original User will use those and your own code can use the extensions you included (that no other code is relying on anyway). It is not a way to replace the User (or any other) model everywhere with something of your own creation.
Maybe in this case, the old way of using UserProfile
would be a better choice?
Sorry if I’m not helping much.
- [Django]-Sending email from webserver – django python
- [Django]-TypeError can't pickle function objects (Django caching)