I know this question has been asked hundreds of times, but most of them contain -accepted- answers that are not valid anymore. Some of them are for Django 1.5, some of them are
An article about the topic: How to Extend Django User Model
What I use is the One-To-One approach:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="profile")
#more fields
@staticmethod
@receiver(post_save, sender=User, dispatch_uid="at_user_post_save")
def user_post_save(sender, instance, **kwargs):
#create new profile on user.save() (if necessary)
profile, new = UserProfile.objects.get_or_create(user=instance)
#in view
profile = request.user.profile
UPDATE:
Are there any other caveats? Like what happens when I remove a UserProfile?
UserProfile is the one who holds the relation, so on delete no user should be deleted. You can control what must be the behavior when a user gets deleted via the on_delete kwarg.
Also do they always have the same private keys?
No each class have its own PKs, just the UserProfile holds the PK to its user.
OneToOneField is in conceptually a ForeignKey with an unique=True, the big difference is that the reverse side of the relation do not return a list with 0/1 elements, but the element itself or raise DoesNotExist or None if null=True.
The only thing which I don't like in this approach is that you always have to do 1 more query to get user.profile. I still can't find a good and clean approach to always .select_related('profile') when a new user is fetched from auth, but this is more of a problem of the authentication system rather than the approach itself.