NOT NULL constraint failed: core_profile.user_id

时间:2017-03-22 18:49:16

标签: django python-2.7

I have a model named Profile which is created to extend the User auth model. I have created two forms one is UserForm and ProfileForm. In register.html template I show this two forms and wish to save in the database through the user.

But it constantly shows the exception: Integrity Error

NOT NULL constraint failed: core_profile.user_id

whenever I try to submit the post filling out all the fields and hit submit button.

Here are my models:

from __future__ import unicode_literals

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 update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save()    

And here is my view for posting the forms:

from django.contrib.auth.decorators import login_required
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect

from .forms import SignUpForm, ProfileForm


@login_required
def home(request):
    return render(request, 'home.html')


def signup(request):
    if request.method == 'POST':
        user_form = SignUpForm(request.POST)
        profile_form = ProfileForm(request.POST)
        if user_form.is_valid():
            user = user_form.save()
            profile_form.save()
            user.refresh_from_db()  # load the profile instance created by the signal
            user.profile.birth_date = user_form.cleaned_data.get('birth_date')
            user.save()
            raw_password = user_form.cleaned_data.get('password1')
            user = authenticate(username=user.username, password=raw_password)
            login(request, user)
            return redirect('home')
    else:
        user_form = SignUpForm()
        profile_form = ProfileForm()
    return render(request, 'signup.html', {'user_form': user_form, 'profile_form': profile_form})

And here are the forms:

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

from .models import Profile


class SignUpForm(UserCreationForm):
    birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')

    class Meta:
        model = User
        fields = ('username', 'password1', 'password2', 'birth_date')


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

Thank you,

2 个答案:

答案 0 :(得分:2)

当您尝试保存profile_form时,它不知道它与哪个用户相关。在您的情况下,当您保存用户表单时,它将创建配置文件,您需要做的只是更新您保存的用户的配置文件,所以我建议如下:

def signup(request):
    if request.method == 'POST':
        user_form = SignUpForm(request.POST)
        profile_form = ProfileForm(request.POST)
        if user_form.is_valid():
            user = user_form.save()
            user.profile.bio = profile_form.cleaned_data.get('bio')
            user.profile.location = profile_form.cleaned_data.get('location')
            user.profile.save()  

     ...

答案 1 :(得分:0)

除了@Gagik Sukiasyan的回答:我还添加了一些其他措施来减少错误/减轻生活负担:

  • transaction.atomic->如果发生错误,说明数据库正在回滚
  • and profile_form.is_valid()确保profile_form已验证
  • 我没有手动检查配置文件属性,而是添加了一个循环

修改后的代码:

from django.db import transaction

@transaction.atomic
def register(request):
    """ register a new user view """
    if request.method == 'POST':
        user_form = UserRegisterForm(request.POST)
        profile_form = ProfileForm(request.POST)
        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            for field in profile_form.changed_data:
                setattr(user.profile, field, profile_form.cleaned_data.get(field))
            user.profile.save()