'I keep getting RelatedObjectDoesNotExist at /admin/login/. How do I successfully create user profiles in Django via a one to one relationship?
I'm trying to extend the built-in user and add some more information to it. I have two apps in my django project- general and user_details. Inside my user_details app, in the models.py file, I have the following...
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from general.models import Ward
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
firstname = models.CharField(max_length=20)
middlename = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
loc_id = models.CharField(max_length=8, unique=True)
ward = models.ForeignKey(Ward, related_name="wards", on_delete=models.CASCADE)
phone = models.CharField(max_length=10, unique=True)
address = models.CharField(max_length=255)
postal_code = models.CharField(max_length=15)
def __str__(self):
return "{} {}".format(self.user.first_name, self.user.last_name)
class Meta:
verbose_name_plural = "User details"
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
else:
instance.profile.save()
I have successfully done this before but today for some reason when I try to log in via the django admin, I keep getting the RelatedObjectDoesNotExist at /admin/login/, no such column: user_details_profile.id
. There are no other components involved, no views or any of that. It's just models and the admin panel. I'm trying to get the model to show in the admin panel but I ran into this error every time I try to log in.
Here is the traceback http://dpaste.com/0W7653C.
Can anyone tell me what I am doing wrong please and how I can get it to work. Help.
Solution 1:[1]
If you define a OneToOneField
that does not mean that every object of the targeted model contains an object from the referencing model. A OneToOneField
in essence is a ForeignKey
with a unique=True
(and some extra logic to do proper naming).
Here it thus means that although every Profile
has a related user, not every user has a Profile
. It is possible that there are User
s for which no Profile
exists.
If you thus query some_user.profile
there are two scenario's that can unfold:
- there is a related
Profile
object that is the fetched, and returned; or - there is no such object, and then it raises a
RelatedObjectDoesNotExist
error.
There have been some proposals to return None
in the latter case, but due to backwards compatibility, this will probably not be implemented in the (near) future, or implemented at all.
So you probably have a user for which there is no profile. Based on the full traceback, the error happens on the line instance.profile.save()
. We can fix this by creating a profile in case there is no such profile:
from django.core.exceptions import ObjectDoesNotExist
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
try:
instance.profile.save()
except ObjectDoesNotExist:
Profile.objects.create(user=instance)
We thus check if the instance
has a .profile
that leads to a Profile
object. In case it has not, it will raise an exception, and then we create one.
This is also more in the Easier to Ask Forgiveness than Permission (EAFP) spirit of Django.
Solution 2:[2]
Just in case someone else might face this same problem: Try creating a python file in the app of your project that's implementing the registration or sign up and call it "signals.py" and add the following code snippet to it. It worked for me perfectly.
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender = User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user = instance
def save_profile(sender, instance, **kwargs):
instance.profile.save()
Solution 3:[3]
Use this. It will work
from django.core.exceptions import ObjectDoesNotExist
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
try:
instance.profile.save()
except ObjectDoesNotExist:
Profile.objects.create(user=instance)
Solution 4:[4]
you just go in your admin page and create a profile of the user you want to login..... and this time I am sure your will not get this type of error again.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Willem Van Onsem |
Solution 2 | Frank Fayia Kendemah |
Solution 3 | Yevgeniy Kosmak |
Solution 4 |