0
votes

i Use One-To-One Link With a User Model (Profile) and i got this error when i try to make user registration Cannot assign "(, True)": "Profile.user" must be a "User" instance. and this is user_registration uses in my project thanks for help

def user_registration(request):
    form = UserRegistrationForm()
      if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            structure= form.cleaned_data['structure'].id
            user = User.objects.get_or_create(username=username,  password=password)
            profile=Profile.objects.create(structure_id=structure,user=user)
            profile.save()
            messages.success(request,
            'Enregistrement avec succés {}'.format(user.username))
        return HttpResponseRedirect(reverse('compte:login'))   
    else:
        form = UserRegistrationForm()
        return render(request,'compte/register.html',{'form':form})

this is my traceback :

[01/Aug/2019 22:01:13] "GET /compte/register/ HTTP/1.1" 200 2194 [01/Aug/2019 22:01:16] "GET /static/js/popper.min.js HTTP/1.1" 404 1773 [01/Aug/2019 22:01:16] "GET /static/js/jquery-3.3.1.slim.min.js HTTP/1.1" 404 1806 [01/Aug/2019 22:01:16] "GET /static/js/bootstrap.min.js HTTP/1.1" 404 1782 [01/Aug/2019 22:01:16] "GET /compte/register/ HTTP/1.1" 200 2194 [01/Aug/2019 22:01:16] "GET /static/js/jquery-3.3.1.slim.min.js HTTP/1.1" 404 1806 [01/Aug/2019 22:01:16] "GET /static/js/popper.min.js HTTP/1.1" 404 1773 [01/Aug/2019 22:01:16] "GET /static/js/bootstrap.min.js HTTP/1.1" 404 1782 Internal Server Error: /compte/register/ Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner response = get_response(request) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response response = self.process_exception_by_middleware(e, request) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/Users/mac/Desktop/investissement/Invest_App/compte/views.py", line 38, in user_registration profile=Profile.objects.create(structure_id=structure,user=user) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/query.py", line 420, in create obj = self.model(**kwargs) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/base.py", line 483, in init _setattr(self, field.name, rel_obj) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/django/db/models/fields/related_descriptors.py", line 301, in set super().set(instance, value) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site- packages/django/db/models/fields/related_descriptors.py", line 211, in set self.field.remote_field.model._meta.object_name, ValueError: Cannot assign "(, True)": "Profile.user" must be a "User" instance. [01/Aug/2019 22:01:25] "POST /compte/register/ HTTP/1.1" 500 91942

2

2 Answers

1
votes

get_or_create returns a tuple of the item and a boolean indicating whether it was created. You should capture both:

user, created = User.objects.get_or_create(username=username,  password=password)
profile = Profile.objects.create(structure_id=structure,user=user)

However, you shouldn't do this either. By doing this you're ensuring that the password is saved without hashing; and in any case, username is a unique field, so the form will not be valid if the username already exists.

Call form.save directly:

user = form.save()

Note also, you don't need to call profile.save(), as create saves the item itself.

0
votes

A .get_or_create(..) [Django-doc] will return a 2-tuple with the first item the object generated, and the second a boolean that specifies if it created a new object. You thus can use iterable unpacking here, to get access to the first element.

def user_registration(request):
    form = UserRegistrationForm()
      if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            structure = form.cleaned_data['structure'].id
            user, __ = User.objects.get_or_create(username=username,  password=password)
            profile = Profile.objects.create(structure_id=structure,user=user)
            profile.save()
            messages.success(request, 'Enregistrement avec succés {}'.format(user.username))
        return HttpResponseRedirect(reverse('compte:login'))   
    else:
        form = UserRegistrationForm()
        return render(request,'compte/register.html',{'form':form})

That being said, the above will not work, since passwords are not saved as raw text in the database, but hashed. You this will need to set the password with .set_password(..) [Django-doc]. You might want to use .update_or_create(..) [Django-doc] for your Profile, to prevent errors in case the profile already exists for that user:

def user_registration(request):
    form = UserRegistrationForm()
      if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']
            structure = form.cleaned_data['structure'].id
            user, __ = User.objects.get_or_create(username=username)
            user.set_password(password)
            user.save()
            Profile.objects.update_or_create(
                user=user,
                defaults={'structure_id': structure}
            )
            messages.success(request, 'Enregistrement avec succés {}'.format(user.username))
        return redirect('compte:login')
    else:
        form = UserRegistrationForm()
        return render(request,'compte/register.html',{'form':form})