0

I extended the Django User Model and added my own fields, and am currently working on filling out these fields during registration. The form seems to be working correctly, with everything apart from the saving.

I used this to help me.

Here is the extension of the User Model:

class StudentProfile(models.Model):
    user = models.OneToOneField(User, null = True, related_name='user', on_delete=models.CASCADE)
    teacher = models.BooleanField(default = False)
    school = models.CharField(max_length = 50)

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


post_save.connect(create_StudentProfile, sender = User)

Here is my Form:

class StudentRegistrationForm(UserCreationForm):
    email = forms.EmailField(required = True)
    school = forms.CharField(required = True)

    def __init__(self, *args, **kwargs):
        super(StudentRegistrationForm, self).__init__(*args, **kwargs)
        self.fields['username'].help_text = ''
        self.fields['password2'].help_text = ''


    class Meta:
        model = User

        fields = (
            'username',
            'first_name',
            'last_name',
            'email',
            'school',
            'password1',
            'password2'            
        )

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


        student_profile = StudentProfile(user = user, school = self.cleaned_data['school'])

        if commit:
            user.save()
            student_profile.save()

        return user, student_profile

Here is my view:

def registration(request):
    if request.method == 'POST':
        form = StudentRegistrationForm(request.POST)
        if form.is_valid():
            user, user_profile = form.save(commit = False)
            form.save()
            return render(request, 'accounts/home.html')
        else:
            args = {'form': form}
            return render(request, 'accounts/reg_form.html', args)

    else:
        form = StudentRegistrationForm()

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

Here is my Traceback:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 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
  337.         return Database.Cursor.execute(self, query, params)

The above exception (NOT NULL constraint failed: userprofile_studentprofile.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
  39.             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
  187.                 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
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/wtreston/GDrive/LesRev/lesssonreview/userprofile/views.py" in registration
  13.             form.save()

File "/Users/wtreston/GDrive/LesRev/lesssonreview/userprofile/forms.py" in save
  41.             student_profile.save()

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in save
  796.                        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
  824.             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
  908.             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
  947.                                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
  85.                 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
  1045.         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
  1054.                 cursor.execute(sql, params)

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

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 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__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 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
  337.         return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /users/
Exception Value: NOT NULL constraint failed: userprofile_studentprofile.user_id

Thanks!

wtreston
  • 1,051
  • 12
  • 28

3 Answers3

1

You have to create a user using User model then you have to pass this user to StudentProfile because its a onetoone field to you StudentProfile.

def save(self, request):
        form = StudentRegistrationForm(request.POST)
        user = User.objects.create(first_name=form.cleaned_data['first_name'],
                            last_name=form.cleaned_data['last_name'],
                            email=form.cleaned_data['email'],
                            username=form.cleaned_data['username'])
        user_profile = StudentProfile.objects.create(user=user,
                                                teacher=form.cleaned_data['teacher'],
                                                school=form.cleaned_data['school'])


        return user, student_profile
Arpit Solanki
  • 9,567
  • 3
  • 41
  • 57
0

It looks like the use object is not being saved,so that it can store its reference StudentProfile model.

AR7
  • 366
  • 1
  • 16
0

There are a number of issues here.

The immediate problem is that you're creating the UserProfile in two places. You've registered a signal handler - create_StudentProfile - that creates one automatically when the User is created; but you're also creating a new one in the form's save method.

You should consider whether you really need that signal handler. If you're always going to create the User via this form, then that handler is unnecessary.

If you do decide you need the signal, then you'll need to redo your save method to take account of it. Something like:

def save(self, commit=True):
    user = super(StudentRegistrationForm, self).save(commit = False)
    if commit:
        user.save()
        profile = user.userprofile
    else:
        profile = UserProfile(user=user)

    profile.school = self.cleaned_data['school']

    if commit:
        profile.save()

    return user, student_profile

You'll note that there's no need to set the email and name, as these are done by the form already in the super call.

The second issue is that you are calling the save method twice in your view. Don't do that.

    if form.is_valid():
        user, user_profile = form.save()
        return render(request, 'accounts/home.html')
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I have removed the signal handler and changed the code in my views.py, however I am still getting the same error: "IntegrityError at /users/ NOT NULL constraint failed: userprofile_studentprofile.user_id". The user is being created and added to the database, however, the added fields such as school are not being saved. – wtreston Jun 12 '17 at 12:53
  • You shouldn't do both of those things, they were alternatives. You still need to create the profile somewhere. – Daniel Roseman Jun 12 '17 at 12:54
  • Im confused... Sorry. From my understanding from what you wrote, the signal handler made the StudentProfile, as well as one in the Forms save method. As I will only be adding users through this form, I removed the signal handler, and left my save method as it was. I then updated the save method in my view. I dont understand what you mean by I shouldnt have done both these things? Thanks – wtreston Jun 12 '17 at 13:02