0
votes

I'm trying to populate a User profile field at user registration (I've read that this is not recommended however is required for my app)

model.py

class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)

twitter = models.CharField(max_length=50)

def create(sender, **kwargs):
    if kwargs['created']:
        user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create, sender=User)

view.py

def register(request):
if request.method == 'POST':
    form = RegForm(request.POST)
    if form.is_valid():
        form.save()
        return redirect('/home')
else:
    form = RegForm()

    args = {'form': form}
    return render(request, 'home/registration_form.html', args)

form.py

class RegForm(UserCreationForm):
    email = forms.EmailField(required=True)
    username = forms.CharField(max_length=50, required=True)
    twitter = forms.CharField(max_length=50, required=True)

    class Meta:
         model = User
         fields = (
            'username',
            'twitter',
            'first_name',
            'last_name',
            'email',
            'password1',
            'password2'
        )

    def save(self, commit=True):
        user = super(RegForm, self).save(commit=False)
        user.username = self.cleaned_data['username']
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']

        user.email = self.cleaned_data['email']
        user.userprofile.twitter = self.cleaned_data['twitter']

       if commit:
           user.save()

       return user

Currently, I'm getting the error "User has no userprofile"

(first time using Django, sorry if this is a silly question, I couldn't find anything that helped online)

Traceback:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py" in execute 298. return Database.Cursor.execute(self, query, params)

The above exception (NOT NULL constraint failed: app_userprofile.user_id) was the direct cause of the following exception:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner 34. response = get_response(request)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 126. response = self.process_exception_by_middleware(e, request)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response 124. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/IS/Desktop/Project/website/app/views.py" in register 37. form.save()

File "/Users/IS/Desktop/Project/website/app/form.py" in save 42. profile.save()

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in save 718. force_update=force_update, update_fields=update_fields)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in save_base 748. updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in _save_table 831. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in _do_insert 869. using=using, raw=raw)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method 82. return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/query.py" in _insert 1136. return query.get_compiler(using=using).execute_sql(return_id)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql 1289. cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute 100. return super().execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute 68. return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in _execute_with_wrappers 77. return executor(sql, params, many, context)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/utils.py" in exit 89. raise dj_exc_value.with_traceback(traceback) from exc_value

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in _execute 85. return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py" in execute 298. return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /app/register/ Exception Value: NOT NULL constraint failed: app_userprofile.user_id

1
I don't see a UserProfile field in your code. Where is it defined?farooq
@farooq it is the automatic reverse relation for the one to one field from UserProfile to User.Daniel Roseman

1 Answers

0
votes

Not sure where you read that you shouldn't do this; it's fine.

Since you're creating the User, you also need to create the UserProfile.

user = super(RegForm, self).save(commit=False)
profile = UserProfile(user=user, twitter=form.cleaned_data["twitter"]
if commit:
    user.save()
    profile.save()

But now you've done this, you should remove that signal. You don't need it.

Note, you don't need to set username, first_name or last_name, the form will do that for you.