NOT NULL constraint failed: core_profile.user_id - django

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,

When you are trying to save the profile_form, it doesn't know to which user it is related to. And in your case, when you save the user form, it will create the profile, and what you need to do is just update the profile of you saved user, so I suggest something like:
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()
...

In addition to #Gagik Sukiasyan's answer: I added some additional things to reduce errors / ease your life:
transaction.atomic -> if errors occur, the database is being rolled back
and profile_form.is_valid() makes sure profile_form is validated
instead of going through the profile attributes manually I added a loop
Modified Code:
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()

Related

ValueError at /profile/ ModelForm has no model class specified. Error django

Iam coding in django and trying to figure how to update profile of a user in my app
Please help me Iam trying to learn how to code and this is a big barrier for me to learn
here's models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete= models.CASCADE)
image = models.ImageField(default='default.jpg',upload_to="profile_pics")
def __str__(self):
return f'{self.user.username} Profile'
here's my views.py:
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
messages.success(request, f'Yor account has been created! You are now able to login')
return redirect('/login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html',{'form': form})
#login_required
def profile(request):
u_form = UserUpdateForm(instance = request.user)
p_form = ProfileUpdateForm(instance= request.user.profile)
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request, 'users/profile.html', context)
Iam getting error at 'u_form':u_form,
and This is my 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 UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1','password2']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email']
class ProfileUpdateForm(forms.ModelForm):
model = Profile
field = ['image']
Iam getting my error at this
p_form = ProfileUpdateForm()
In the ProfileUpdateForm you defined the model class name without the Meta class
Model name and fields should be defined inside the Meta class like this:
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']

Django CRUD - create and update view doesn't work

I'm really new to Django and I want to teach myself by making a simple note. I maked a simple form for creating a new note but I don't know how to make this just for the user is logged in. What I mean is that I want the user field from the creationNoteForm to be removed and the note to be sumbitted automatically for the person who is logged in. Hope that I was clear enough.
Here is my "view.py":
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from .forms import CreateUserForm, CreateNoteForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import *
# Create your views here.
def loginPage(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.info(request, 'Username or pasword is incorrect')
context = {}
return render(request, 'accounts/login.html', context)
def registerPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
user = form.cleaned_data.get('username')
messages.success(request, 'Account was created for '+ user)
return redirect('home')
context = {'form': form}
return render(request, 'accounts/register.html', context)
def logoutUser(request):
logout(request)
return redirect('login')
#login_required(login_url='login')
def home(request):
if request.user.is_authenticated:
username = request.POST.get('username')
context = {'username': username}
return render(request, 'accounts/home.html', context)
#login_required(login_url='login')
def notes(request):
username = None
if request.user.is_authenticated:
username = request.user.username
user_id = request.user.pk
user_notes = Note.objects.filter(user=user_id)
context = {
'user_notes': user_notes,
'username': username,
#'user_id' : user_id,
}
return render(request, 'accounts/notes.html', context)
def createNote(request):
# username = request.user.username
# user_id = request.user.pk
# user_notes = Note.objects.filter(user=user_id)
form = CreateNoteForm()
if request.method == 'POST':
form = CreateNoteForm(request.POST)
if form.is_valid():
form.save()
return redirect('notes')
context = {
'form': form,
}
return render(request, 'accounts/create_note.html', context)
def deleteNote(request, pk):
note = Note.objects.get(id=pk)
if request.method == 'POST':
note.delete()
return redirect('notes')
context = {'note': note}
return render(request, 'accounts/delete.html', context)
def updateNote(request, pk):
note = Note.objects.get(id=pk)
form = CreateNoteForm(instance=note)
if request.method == 'POST':
form = CreateNoteForm(request.POST, instance=note)
if form.is_valid():
form.save()
return redirect('notes')
context = {'form': form, 'note': note}
return render(request, 'accounts/update.html', context)
"forms.py":
from django.forms import ModelForm
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Note
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class CreateNoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ['user', 'title', 'text']
and "models.py" just in case:
from django.db import models
from django.contrib.auth.models import User
class Note(models.Model):
#user = models.ForeignKey(Person, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(User, null=True,on_delete=models.SET_NULL)
title = models.CharField(max_length=200, null=True)
text = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Thank you and sorry I am a noob!

Django's authentication form is always not valid

I was trying to implement a basic login system using Django with a custom user using the AbstractUser class.
Here is my models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser
class Stock(models.Model):
stock_name = models.CharField(max_length=10)
stock_price = models.FloatField()
def __str__(self):
return self.stock_name
class CustomUser(AbstractUser):
stocks = models.ManyToManyField(Stock)
def __str__(self):
return self.username
My forms.py:
from .models import CustomUser,Stock
from django.contrib.auth.forms import AuthenticationForm
class loginform(AuthenticationForm):
class Meta:
model = CustomUser
fields = ('username', 'password')
My views.py:
def successful_login(request, pk):
user = get_object_or_404(CustomUser, pk=pk)
return render(request, '../templates/stock_portfolio.html', {'user':user})
def loginview(request):
err=0
if request.method=="POST":
form = loginform(request.POST)
pdb.set_trace()
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
pdb.set_trace()
login(request, user)
pk = user.id
pdb.set_trace()
return redirect('successful_login', pk=pk)
else:
err=1
return render(request,'../templates/login.html',{'response':err,'form':form})
else:
form = loginform()
return render(request, '../templates/login.html',{'form':form})
While logging using pdb here is what I am getting for the form.
<loginform bound=False, valid=Unknown, fields=(username;password)>
How do I proceed now?
Answering this since I just had the same issue and found the problem. Change your
form = loginform(request.POST)
to
form = loginform(data=request.POST)
Worked like a charm for me.

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.
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')
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.

How to save the users last logout time

I am looking to save the users last logout time.My idea was to add it to the users profile model. I am using Django 1.11.15
Example:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
last_logout = models.DateTimeField(blank=True, null=True)
below is how I created my profile model just for reference
def signup(request):
if request.method == 'POST':
form = UserCreateForm(request.POST or None)
if form.is_valid():
new_user = form.save()
Profile.objects.create(user=new_user)
return redirect('accounts:edit_profile')
else:
form = UserCreateForm()
context = {'form': form}
return render(request, 'accounts/signup.html', context)
Below is what I intend to do. Is this the correct way. I want to add to django's default signout/logout method I am not sure if its called signout or logout
class LoggedOut(TemplateView):
template_name = 'logged_out.html'
def signout(self):
"""logout user """
self.request.user.profile.last_logout = datetime.now()
self.request.user.profile.save()
My URL's
url(r'^loggedout/$', views.LoggedOut.as_view(), name='loggedout'),
You can use Django logout signal for such purpose.
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
#receiver(user_logged_out)
def sig_user_logged_out(sender, user, request, **kwargs):
user.profile.last_logout = datetime.now()
user.profile.save()