Trying to extend User to UserProfile in form Django - python

Hi I am having serious trouble this getting this form to work. When I try to run my program it gets to print("4") then throws the error
UNIQUE constraint failed: slug_trade_app_userprofile.user_id
To be clear the new user i am creating doesnt exist prior to clicking submit on the form
It seems like profile is trying to create a new user again but since (i think) user created a new user, that user already exists its throwing the error. HELP!!
Views.py
def signup(request):
if request.method == 'POST':
user_form = UserForm(data=request.POST)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
print("1")
user = user_form.save(commit=False)
user.save()
print("2")
profile = profile_form.save(commit=False)
print("3")
profile.user = user
print("4")
profile.save()
print("5")
user = authenticate(username=user_form.cleaned_data['email'],
password=user_form.cleaned_data['password1'],
)
login(request, user)
return redirect('/home')
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, 'slug_trade_app/signup.html', {'user_form': user_form, 'profile_form': profile_form})
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField(upload_to='static/profile_pictures', blank=True )
bio = models.TextField(max_length=500, blank=True)
on_off_campus = models.CharField(max_length=3,
default="on",
choices=CAMPUS_STATUS)
forms.py
class UserForm(UserCreationForm):
email = forms.EmailField(required=False)
class Meta:
model = User
fields = (
'first_name',
'last_name',
'email',
'password1',
'password2',
)
def save(self, commit=True):
user = super(UserForm, self).save(commit=False)
user.username = self.cleaned_data['email']
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 UserProfileForm(forms.ModelForm):
class Meta():
model = UserProfile
fields = ('profile_picture', 'bio', 'on_off_campus')

Try profile_form = UserProfileForm(instance=request.user) Also I believe profile.user = user should be profile.user = request.user otherwise user refers to the user form not the user instance

Related

matching query does not exist - Django

I am working on a registration page. I extended django's User model to add additional fields. I have two forms connected with OnetoOnefield. I am getting this error.
DoesNotExist at /register/
Influencer matching query does not exist.
I think what I am doing wrong is creating User and Influencer model at the same time.
My models.py file:
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 Influencer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True, null=True)
ig_url = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return f"{self.user.first_name} {self.user.last_name}"
#receiver(post_save, sender=User)
def create_influencer(sender, instance, created, **kwargs):
if created:
Influencer.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_influencer(sender, instance, **kwargs):
instance.influencer.save()
My forms.py file:
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class InfluencerProfileForm(forms.ModelForm):
class Meta:
model = Influencer
fields = ('bio', 'ig_url')
My views.py file:
def register(request):
user_form = UserForm()
profile_form = InfluencerProfileForm()
if request.method == 'POST':
user_form = UserForm(request.POST, instance=request.user)
profile = Influencer.objects.get(user=request.user)
profile_form = InfluencerProfileForm(request.POST, instance=profile)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
messages.success(request, 'Your profile was successfully updated!')
return redirect('settings:profile')
else:
messages.error(request, 'Please correct the error below.')
return render(request, 'accounts/register.html', {
'user_form': user_form,
'profile_form': profile_form
})
I think the problem is in two places. One, you have a signal which creates Influencer instance where you al. Second, you are assuming you will have a Influencer instance before creating one. You can remove the signals and try with the following code:
def register(request):
user_form = UserForm(request.POST or None)
profile_form = InfluencerProfileForm(request.POST or None)
if request.method == 'POST':
if request.user.is_authenticated:
user_form = UserForm(request.POST, instance=request.user)
try:
profile_form = InfluencerProfileForm(request.POST, instance=request.user.influencer) # due to OneToOne relation, it will work
except:
pass
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
messages.success(request, 'Your profile was successfully updated!')
return redirect('settings:profile')
else:
messages.error(request, 'Please correct the error below.')
return render(request, 'accounts/register.html', {
'user_form': user_form,
'profile_form': profile_form
})

django - extending User model for registration

I am really new to django. I have a model and 2 forms like this below extending the User model. The UserProfile is linked to the user model which would be where I have my extra field. I have seen numerous posts but still was't able to solve it. I would like to save the profile with additional parameters like the phone number stated below when the registration form is submitted, I have been spending hours trying to make it work, thanks a lot for your help in advance:
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length = 50)
phone_number = models.CharField(max_length=12)
#In form.py
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ['username',
'first_name',
'last_name',
'email',
'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 RegistrationFormProfile(forms.ModelForm):
phone_number = forms.CharField(max_length = 12)
class Meta:
model = UserProfile
fields = [
'phone_number',
]
def save(self, commit=True):
profile.phone_number = self.cleaned_data['phone_number']
if commit:
profile.save()
return profile
#In views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
profileForm = RegistrationFormProfile(request.POST)
if form.is_valid():
user = form.save()
if(profileForm.is_valid()):
profileForm.save()
return redirect('accounts/profile')
else:
return redirect('accounts/wrong')
else:
form = RegistrationForm()
profileForm = RegistrationFormProfile()
args = {'form' : form, 'profileForm' : profileForm}
return render(request, 'users/reg_form.html', args)

Django 1.10 IntegrityError on register

I'm trying to set up a registration page and I have a model CafeUser which serves as the profile for the User model. I used a tutorial to set up a signal receiver so I could create a CafeUser for all new registered users.
models.py:
class CafeUser(models.Model):
user = models.ForeignKey(User, unique=True, related_name="cafeuser")
phone_number = models.CharField(max_length=15)
birth_date = models.DateField('birthdate')
def __str__(self):
return self.user.first_name + " " + self.user.last_name
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
CafeUser.objects.create(user=instance)
views.py:
def register(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.cafeuser.birth_date = form.cleaned_data.get('birth_date')
user.cafeuser.phone_number = form.cleaned_data.get('phone_number')
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('cafe:index')
else:
form = SignUpForm()
return render(request, 'cafe/register.html', {'form': form})
forms.py
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
birth_date = forms.DateField(help_text='Rquired.')
phone_number = forms.CharField(max_length=15)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2',)
When I try testing the registration, the user is created, however, the CafeUser is not:
IntegrityError at /register/ null value in column "birth_date"
violates not-null constraint DETAIL: Failing row contains (7, 8,
null, ).
register.html:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="submit">Register</button>
</form>
Please let me know how to fix this and any other tips you might have for improving this unit of code.
The problem was that the CafeUser was not saving. Based on what I read in the docs somewhere, I had thought that calling user.save() was supposed to automatically call save() on the profile module as well - and I'm still not sure why it doesn't. So I just wrote the call user.cafeuser.save() myself anyway:
if form.is_valid():
user = form.save()
user.refresh_from_db()
user.cafeuser.birth_date = form.cleaned_data.get('birth_date')
user.cafeuser.phone_number = form.cleaned_data.get('phone_number')
user.cafeuser.save() # Apparently this had to be added
user.save()
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return redirect('cafe:index')

RelatedObjectDoesNotExist User has no Profile

I am new to Django.I am creating a user registration by using the built in Django User model and Usercreation form. I am trying to extend the built-in User Model in Django so I can include an extra field company name.I am encountering this recurring error below.I would really appreciate any help in trying to solve this problem.
RelatedObjectDoesNotExist User has no Profile
(1)Here is my Model.py of the Profile model
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Company_name = models.CharField(max_length=30)
#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()
(2.)Here is my views.py.I am trying to update the profile model each time a new user instance is created.It seems like I have to link the create_user_profile and save_user_profile functions to my view but I am not too sure how to do this.
def Register(request):
if request.method == 'POST':
User_form = RegisterRecruiterForm(request.POST, instance=request.user)
Profile_form = ProfileForm(request.POST, instance=request.user.profile)
if User_form.is_valid() and Profile_form. is_valid():
User_form.save()
Profile_form.save()
return HttpResponse('you are now registered')
else:
User_form = RegisterRecruiterForm(instance=request.user)
Profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'Register.html', {
'User_form': User_form,
'Profile_form': Profile_form
})
3.Here is my forms.py.
class RegisterRecruiterForm(UserCreationForm):
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super(RegisterRecruiterForm, self).save(commit=False)
user.email(self.cleaned_data["email"])
user.username(self.cleaned_data["username "])
user.password(self.cleaned_data["password1 "])
user.password(self.cleaned_data["password2 "])
if user.password1 != user.password2:
raise forms.validationError("Password do not match")
return Profile.Company_name
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
Company_name = forms.CharField(max_length=10,help_text='Required')
class Meta:
model = Profile
fields = ('Company_name',)
def save(self, commit=True):
Profile = super(ProfileForm, self).save(commit=False)
Profile.Company_name(self.cleaned_data["Company_name"])
if commit:
Profile.save()
return Profile
As I can see, your problem is that you are trying to get "request.user.profile" in this line:
Profile_form = ProfileForm(request.POST, instance=request.user.profile)
In your models the "User" doesn't has a "Profile" but a "Profile" has a "User", so the correct way to get this profile is:
profile = Profile.objects.get(user = request.user)
Profile_form = ProfileForm(request.POST, instance = profile)
This fix your problem with the "RelatedObjectDoesNotExist" error. If you have another error, you can open a new question.
Finally, you "Register" function will be:
def Register(request):
if request.method == 'POST':
User_form = RegisterRecruiterForm(request.POST, instance=request.user)
profile = Profile.objects.get(user = request.user)
Profile_form = ProfileForm(request.POST, instance = profile)
if User_form.is_valid() and Profile_form. is_valid():
User_form.save()
Profile_form.save()
return HttpResponse('you are now registered')
else:
User_form = RegisterRecruiterForm(instance=request.user)
profile = Profile.objects.get(user = request.user)
Profile_form = ProfileForm(request.POST, instance = profile)
return render(request, 'Register.html', {
'User_form': User_form,
'Profile_form': Profile_form
})

How to allow user to change his attributes?

I'm trying to figure out how to allow users to change their profile. I have a Users extended by User Profile (OneToOne).
I was thinking about changing registration view, prefill user's attributes and allow him to change them. But it is not probably the good way.
Could you give me a hint how to do that?
class UserForm(forms.ModelForm):
password1 = forms.CharField(widget=forms.PasswordInput())
password2 = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password1','password2', 'first_name', 'last_name')
def clean(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
return self.cleaned_data
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('telephone','marital_status','how_do_you_know_about_us')
MODELS.PY
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
# ATRIBUTY KTORE BUDE MAT KAZDY
telephone = models.CharField(max_length=40,null=True)
HOW_DO_YOU_KNOW_ABOUT_US_CHOICES = (
('coincidence',u'It was coincidence'),
('relative_or_friends','From my relatives or friends'),
)
how_do_you_know_about_us = models.CharField(max_length=40, choices=HOW_DO_YOU_KNOW_ABOUT_US_CHOICES, null=True)
MARITAL_STATUS_CHOICES = (
('single','Single'),
('married','Married'),
('separated','Separated'),
('divorced','Divorced'),
('widowed','Widowed'),
)
marital_status = models.CharField(max_length=40, choices=MARITAL_STATUS_CHOICES, null=True)
# OD KIAL STE SA O NAS DOZVEDELI
# A STAV
def __unicode__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
def __str__(self):
return '{} {}'.format(self.user.first_name,self.user.last_name)
REGISTRATION VIEW:
def register(request):
if request.method == 'POST':
user_form = UserForm(request.POST)
profile_form = UserProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.set_password(user_form.cleaned_data['password1'])
user.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return register_success(request)
else:
print user_form.errors, profile_form.errors
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request, "auth/registration/register.html",
context={'user_form': user_form, 'profile_form': profile_form})
EDIT:
This is the view I'm trying to create but it does not autofill form:
#login_required
def edit_profile(request):
myUser = request.user
user_form = UserForm(request.POST, instance=myUser)
user_profile_form = UserProfileForm(request.POST, instance=myUser)
context={'user_form': user_form,
'user_profile_form':user_profile_form}
return render(request, 'auth/profiles/my_profile.html', context=context)
In the edit_profile view you added, you're passing your forms a POST request argument. You should only be passing this argument on a POST request. So update your forms to be the following if the request is a GET request:
views.py
user_form = UserForm(instance=myUser)
user_profile_form = UserProfileForm(instance=myUser)
forms.py
# Something like this will only save password if data is entered in one of the password fields
def clean(self):
cleaned_data = super(UserForm, self).clean()
password1 = cleaned_data.get('password1', None)
password2 = cleaned_data.get('password2', None)
old_password = cleaned_data.get('old_password', None)
if password1 or password2:
if password1 != password2:
self._errors['password1'] = 'New Password and Confirm New Password must match.'
self._errors['password2'] = 'New Password and Confirm New Password must match.'
if not self.user.check_password(old_password):
self._errors['old_password'] = 'Your old password was entered incorrectly.'
return cleaned_data
def save(self, request):
user = self.user
if self.cleaned_data.get('password1', None):
user.set_password(self.cleaned_data.get('password1'))
update_session_auth_hash(request, user)
user.save()
return user
For your choices issue, you can specify choices as an argument when specifying widgets for the field.

Categories

Resources