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')
答案 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()