How to update Django user profile from ForeignKey to OneToOneField

In one of my projects for the user profile model was used ForeignKey field.

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)

This leads to a lot of unnecessary queries when you want to access to related data, like:

{% raw %}
{% for item in items %}
    {{ }}
{% endfor %}
{% endraw %}

But as the unique=True, this means that for each user, there is only one profile. For other cases, it is possible to check this with following query:

from django.db.models import Count

In this situation it is better to replace the ForeignKey with OneToOneField.

user = models.OneToOneField(User, related_name='userprofile', primary_key=True, db_column='user_id')
db_column='user_id' #because it already has the required values
related_name='userprofile' #because there may be requests like User.objects.filter(userprofile__company=...)

Then you need to update the database, I use the south, so:

mysqldump .... #for backup
python schemamigration app --auto
python migrate app

You can then make another migration to rename user_id to id:

user = models.OneToOneField(User, related_name='userprofile', primary_key=True, db_column='id')

Then in the templates user.get_profile must be replaced with user.userprofile and with And in the code user.get_profile() with user.userprofile.

After that, you can significantly reduce the number of queries using the necessary select_related, like

comments powered by Disqus