Justin O'Brien
Justin O'Brien

Reputation: 129

Extending User Model Django, IntegrityError

I am trying to extend the User model to create a Profile model. The following code successfully displays a form with the additional fields I specified as location and bio. But when I submit the form only the original username, first_name, last_name, email, and password fields are stored in the database at http://127.0.0.1:8000/admin, none of my custom fields are stored in the Profile section I added to admin . I also get the following error:

IntegrityError at /accounts/register/
NOT NULL constraint failed: accounts_profile.user_id
Request Method: POST
Request URL:    http://127.0.0.1:8000/accounts/register/
Django Version: 1.11.2
Exception Type: IntegrityError
Exception Value:    
NOT NULL constraint failed: accounts_profile.user_id
Exception Location: /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py in execute, line 328
Python Executable:  /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6

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):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(max_length=500, blank=True)
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

forms.py:

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile

class RegistrationForm(UserCreationForm):
    email = forms.EmailField(required = True)

    class Meta:
        model = User #model User comes with username, email, first name, last name , pass1 and pass2 fields
        fields = (
            'username',
            'email',
            'first_name',
            'last_name',
            'password1',
            'password2'
        )

    def save(self, commit = True):
        user =  super(RegistrationForm, 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']


        if commit:
            user.save()

            return user

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('location','bio')

views.py:

from django.shortcuts import render, redirect  
from .forms import RegistrationForm,ProfileForm



def register(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        profile_form = ProfileForm(request.POST)
        if form.is_valid() and profile_form.is_valid():
            form.save()
            profile_form.save()
            return redirect('login')

    else:
        form = RegistrationForm()
        profile_form = ProfileForm()


    return render(request, 'accounts/register.html', {'form': form, 'profile_form': profile_form})

urls.py:

from django.conf.urls import url
from django.contrib.auth.views import login
from . import views


urlpatterns = [
    # /accounts/
    url(r'^$', views.index, name = 'accounts'),

    # /accounts/register/
    url(r'^register/$',  views.register, name='register'),

    url(r'^login/$', login, {'template_name': 'accounts/login.html'}, name='login'),
]

admin.py:

from django.contrib import admin
from .models import Profile
# Register your models here.

admin.site.register(Profile)
# Register your models here.

Any help would be greatly appreciated.

Upvotes: 0

Views: 634

Answers (2)

Mauricio Cortazar
Mauricio Cortazar

Reputation: 4213

you have to set the relation manually then your view should look like this:

    if form.is_valid() and profile_form.is_valid():
        user_object = form.save()
        a = profile_form.save(commit=False)
        a.user = user_object
        a.save()
        return redirect('login')

Upvotes: 1

Akash D
Akash D

Reputation: 789

you can't do register and profile POST at a time.because your profile model is 1to1field it belongs to Userwhich means existing user can create one user profile.So initially user should create their registered account than only they can create profile.

Upvotes: 0

Related Questions