Django, data forms cannot be saved - django

I have a problem with Django when I would like to get information from the register. I can get their first name, last name, and email but no nickname and graduated schools. I thought i did it correctly since i added nickname and school inside forms.py
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):
first_name = forms.CharField()
last_name = forms.CharField()
nickname = forms.CharField()
school = forms.CharField()
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'password1', 'password2',
'first_name', 'last_name', 'nickname', 'school']
class UserUpdateForm(forms.ModelForm):
first_name = forms.CharField()
last_name = forms.CharField()
nickname = forms.CharField()
school = forms.CharField()
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','first_name', 'last_name', 'nickname', 'school']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['image']
models.py
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
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'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300,300)
img.thumbnail(output_size)
img.save(self.image.path)
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'Your account has been created! You are now able to log in')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST,
request.FILES,
instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Your account has been updated!')
return redirect('profile')
else:
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)
I have tried to save by adding form.cleaned_data.get in views.py but it still didn't work. I appreciate all help.

The problem is that you are not saving "nickname" and "graduated schools" to any model(based on models.py). First of all, you are inheriting from the user model when you do the following:
'''
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
'''
In doing so you can only save what you have in the Profile model and the User model, which I would recommend reading https://docs.djangoproject.com/en/2.1/ref/contrib/auth/ detailing what does the User model have(username,password, etc.).
Lastly, I would just add the nickname and the graduated schools to the Profile Model and it should work.

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']

how to make profile for each user

I have an app that if a user signs up, the app will automatically make a profile page for it, the sign up and login part works correctly but it doesn't make a profile page, I have to do it in the admin page. How should I solve this problem?
this is my models.py
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'
def save(self):
super().save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
this is my views.py
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'Your Acount Has Been Created You Are Now Be Able to Login')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form':form})
#login_required
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
p_form = ProfileUpdateForm(request.POST ,request.FILES , instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request, f'Your Acount Has Been Updated')
return redirect('profile')
else:
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)
this is my forms.py
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):
class Meta:
model = Profile
fields = ['image']
this is my signals.py
#receiver(post_save, sender=User)
def create_profile(sender, instance, created , **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
and this is my apps.py:
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals
The only reason I can see that would cause this is that the signals aren't registering properly, make sure the config is referenced in the app's init.py file:
# my_app.__init__.py
default_app_config = 'my_app.apps.MyAppConfig'
Alternatively, move the signals to the models.py file and see if they fire when the User is created. As a last resort, try creating the profile in the view when the User form is saved.

Django edit user profile after success registration

I try to configure the project in such a way that the user goes through the primary registration, then logged in and from the personal cabinet could add additional information about himself. There are no problems with the initial registration, but when you try to change and supplement the information, there are no changes.
My UserProfile model:
models.py
from customuser.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50, blank=True)
surname = models.CharField(max_length=50, blank=True, default = None)
avatar = models.ImageField(upload_to = 'images/profile/%Y/%m/%d/', blank=True, null=True)
position = models.ForeignKey('Position',blank=True, default=None)
role = models.ForeignKey('Role', blank=True, default=None)
company = models.ForeignKey('Company',blank=True, default=None)
status = models.ForeignKey('Status', blank=True, default=None)
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
forms.py
from django import forms
from django.forms import ModelForm
from client.models import Profile
class UserProfileForm(ModelForm):
class Meta:
model = Profile
exclude = ['user']
views.py
from customuser.models import User
from client.models import Profile
from .forms import UserProfileForm
def edit_user(request, pk):
user = User.objects.get(pk=pk)
form = UserProfileForm(instance=user)
if request.user.is_authenticated() and request.user.id == user.id:
if request.method == "POST":
form = UserProfileForm(request.POST, request.FILES, instance=user)
if form.is_valid():
update = form.save(commit=False)
update.user = user
update.save()
return HttpResponse('Confirm')
else:
form = UserProfileForm(instance=user)
return render(request, 'client/edit.html', {'form': form})
UserProfileForm is form for Profile model, so instance passed to the form should be profile, not user. You shoud do something like this:
def edit_user(request, pk):
user = User.objects.get(pk=pk)
profile = user.profile
form = UserProfileForm(instance=profile)
if request.user.is_authenticated() and request.user.id == user.id:
if request.method == "POST":
form = UserProfileForm(request.POST, request.FILES, instance=profile)

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.

NOT NULL constraint failed: core_profile.user_id

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()