CherryGot
CherryGot

Reputation: 39

Django: Cannot assign "<Profile: Profile object (None)>": "Profile.user" must be a "User" instance

I'm trying to create a signup form using Django. I'm getting this error while submitting the form.

Here's what I've done.

models.py

from django.db import models 
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    profile_ID  = models.IntegerField(primary_key=True)
    user        = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar      = models.ImageField(upload_to='img/',     default='img/none/default-avatar.png')

def updateUserProfile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()

post_save.connect(updateUserProfile, dispatch_uid="app_models_updateUserProfile")    

views.py

from django.shortcuts import render, redirect
from django.views import View
from django.contrib.auth import login, authenticate
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
# Create your views here.

class SignUpView(View):
    templateName = 'auth/signup.html'

    def get(self, request, *arg, **kwargs):
        form = UserCreationForm()
        return render(request, self.templateName, {'form': form})

    def post(self, request, *arg, **kwargs):
        form = UserCreationForm(request.POST, request.user)
        if form.is_valid():
            user = form.save()
            username = form.cleaned_data.get('username')
            raw_password = form.cleaned_data.get('password1')
            user = authenticate(username=username, password=raw_password)
            login(request, user)
            return redirect('/')
        return render(request, self.templateName, {'form': form})

From the error traceback, I can see that the error is because of the fact that somehow two signup requests are being sent at a time. It shouldn't happen 'cause I've used this,

post_save.connect(updateUserProfile, dispatch_uid="app_models_updateUserProfile")

Here's the traceback,

Error traceback #1

Error traceback #2

I guess I've done something silly. Please help!

Upvotes: 1

Views: 1649

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599600

You've connected your signal handler to all post-save signals. So when you call instance.profile.save(), it's called again on the profile itself, which it then tries to assign as the user attribute in another newly-created Profile.

You should restrict it to only be called on post-save for User:

post_save.connect(updateUserProfile, sender=User, ...)

(Not sure why you've specified the dispatch_uid; you normally don't need that.)

Upvotes: 1

Related Questions