RelatedObjectDoesNotExist: User has no userprofile

33,653

Solution 1

You have to create a userprofile for the user first:

profile = UserProfile.objects.create(user=request.user)

In your views.py you can use get_or_create so that a userprofile is created for a user if the user doesn't have one.

player, created = UserProfile.objects.get_or_create(user=request.user)

UPDATE: For automatically creating user profiles every time a new user is made, use signals.

In myapp/signals.py do something like this:

@receiver(post_save, sender=User, dispatch_uid='save_new_user_profile')
def save_profile(sender, instance, created, **kwargs):
    user = instance
    if created:
        profile = UserProfile(user=user)
        profile.save()

Solution 2

If you are getting this error even if you've tried the suggestions above, it may caused by the fact that the first user you had created (with createsuperuser command) does not have a profile.

I was getting this error when I tried to login with that user. I solved it this way:

-Create a new user.

-Undo the changes. (Erase the code you've written for Profile or make them comment lines)

-Log in to your superuser.

-Give admin authorization to newly created user.

Now you can delete the first user. (The user with no profile)

Solution 3

Nothing in what you've done forces the creation of a UserProfile object when a User is created. There are two basic ways of handling this:

  1. If you always want a UserProfile to exist (which seems like the case as you give a default value to score, create a post_save handler that creates a new profile when ever the User object is created (but not every time it's saved, so make sure to check the created argument in the handler).

  2. If it's expected a user may not have a profile, you need to catch the UserProfile.DoesNotExist exception when trying to access it. If you do this frequently, make some kind of helper function.

UPDATED TO ANSWER SIGNAL QUESTION

It also looks like somewhere around here post_save.connect(create_profile, sender=User) should be added?

You would need to define a function called create_profile and then wire it up as you have shown. I typically do this right in the models.py file that includes the sender but in this case where the sender is a built-in Django model and you're already importing that model into the file where you define your UserProfile that's the place to do it. It would look something like:

def create_profile(sender, instance, created, *args, **kwargs):
    # ignore if this is an existing User
    if not created:
        return
    UserProfile.objects.create(user=instance)
post_save.connect(create_profile, sender=User)

Solution 4

I had the same error but i solved it by creating my signals example below

then i edited my apps.py as follows:

`from django.apps import AppConfig

class BlogConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'app_name'

def ready(self):
    import app_name.signals`

Solution 5

First Register profile model in admin.py if not already done.

Create new superuser using ./manage.py createsuperuser.

Log in with new superuser.

From Admin panel click Profile and add new entry and selct user from user dropdown and save.

Share:
33,653

Related videos on Youtube

MrJalapeno
Author by

MrJalapeno

Updated on July 09, 2022

Comments

  • MrJalapeno
    MrJalapeno almost 2 years

    So I've extended my user with the field score like this:

    models.py:

    class UserProfile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        score = models.IntegerField(default=0);
    

    which seemed to be along the lines of the recommended way.

    Then I tried to access the user's userprofile in my views:

    views.py:

    player = request.user.userprofile
    

    which seemed to align with the recommended way as well, but that is where I get my error:

    RelatedObjectDoesNotExist
    User has no userprofile.
    

    If I change userprofile to something else I get another error:

    AttributeError
    'User' object has no attribute 'flowerpot'
    

    When I try the following code:

    print request.user
    print UserProfile.objects.all()
    

    I get the console output:

    post_test1
    []
    

    EDIT
    I have two superusers, seven users I created before extending the user, and one user (post_test1) that I created after extending the user.


    EDIT 2

    It seams clear that what I need is to create a post_save handler that creates a new profile whenever the User object is created.

    This seemed simple enough when I read it, went to the page that was linked to, which was a list of all the signals Django sends. I looked up post_save and it said:

    Like pre_save, but sent at the end of the save() method.

    Alright, so I look up pre_save and it says:

    This is sent at the beginning of a model’s save() method.

    I've interpreted it like this: When I create my user (in my views.py) the save() method should be called, which hasn't been the case up until now, and after that a post_save should be sent(?), which will create a new profile whenever the User object is created!

    So now I'm ready to start looking at examples, so I google:

    django post save example
    Here it looks like I'm supposed to add something that looks like a decorator @receiver(post_save, ...
    Here it looks like I'm supposed to alter multiple files and write a signal definition?
    This one also seems to imply multiple files (including a signals.py)

    It looks like there's a lot more to it than I first thought. Could anyone here either explain how I'm to do this or show me to some good resources on how signals work?

    Right now my create_user view look like this:

    def create_user(request):
        if request.method == "POST":
            form = UserCreationForm(request.POST)
            if form.is_valid():
                username = form.cleaned_data["username"]
                password = form.cleaned_data["password1"]
                new_user = User.objects.create_user(username=username, password=password)
                return redirect('play')
        else:
            form = UserCreationForm()
    
        return render(request, 'antonymapp/create_user.html', {'form': form})
    

    Should I call new_user.save() before returning? If yes, why has it worked up until now? I have a bunch of users that I've created while testing this view. It also looks like somewhere around here post_save.connect(create_profile, sender=User) should be added?

    • Shang Wang
      Shang Wang about 8 years
      RelatedObjectDoesNotExist means there's no userprofile related to request.user, it's kind of obvious, isn't it?
    • MrJalapeno
      MrJalapeno about 8 years
      I extended user with userprofile and still there's no userprofile related to request user. So yeah, you're right. That's obviously the problem I'm asking about here.
    • abhishekgarg
      abhishekgarg about 8 years
      did you setup the userprofile in settings file? for example if your app name is base then you need to add this in your settings file. AUTH_PROFILE_MODULE = 'base.UserProfile'
  • MrJalapeno
    MrJalapeno about 8 years
    Thanks for the answer! What's the recommended way of doing this? Should I do this in the create_user view? Where could I read up on this (wondering for example of how I'd go about creating userprofiles for admin and previously created users but don't want to waste your time with a bunch of follow up questions =)
  • v1k45
    v1k45 about 8 years
    You can either use get_or_create to ensure user has profile when he/she visits the page Or you can create a post_save signal to create profile every time a new user is created.
  • MrJalapeno
    MrJalapeno about 8 years
    Thanks! So I don't have to do anything in my views.py-file? It feels like I've just created a function (save_profile) that I should call somewhere?
  • v1k45
    v1k45 about 8 years
    Nope, you are not required to call it anywhere. It gets executed on its own every time a user is created/updated.
  • MrJalapeno
    MrJalapeno about 8 years
  • Soren
    Soren about 3 years
    Problem, I cannot login with the superuser, because the profile is not there.
  • mfit
    mfit over 2 years
    This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review