django - extending User model for registration - python

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)

Related

Django models RelatedObjectDoesNotExist

i am making an ecom app for Django but when i use a diffrent user i get this error. i think it has something to do with assigning a Customer to a User, as when i manually create a Customer with a User.
Exception Type: RelatedObjectDoesNotExist
Exception Value:
User has no customer.
Exception Location: L:\Django\Website\lib\site-packages\django\db\models\fields\related_descriptors.py in __get__, line 420
Python Executable: L:\Django\Website\Scripts\python.exe
Python Version: 3.8.3
here is my views.py
from django.shortcuts import render
from .models import *
from django.http import JsonResponse
import json
import datetime
from django.contrib.auth.models import User
def store(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0,'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
search = request.GET.get('search')
products = Product.objects.all()
if search != '' and search is not None:
products = products.filter(name__icontains=search)
context= {'products': products, 'cartItems':cartItems}
return render(request, 'store/store.html', context)
...unrelated...
here is my models.py
from django.db import models
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
...unrelated...
========================
when i use the method in the code block it doesn't save the extra fields
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(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST, request.FILES)
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 login')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
but when i try this it saves everything except the passwords
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
def save(self, **kwargs):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.save()
return user
views.py is the same.
I'd suggest to use the Customer model as what you refer to as the user throughout the app. Therefore I would keep the save method for the user as default and add the extra fields to the Customer model.
This makes it also easier to later add extra data of the user when registering. The Customer would be created on registering the user. For example:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
def save(self, **kwargs):
user = super().save()
customer = Customer.objects.create(user=user, first_name=self.cleaned_data.get('first_name'),
last_name=self.cleaned_data.get('last_name'), email=self.cleaned_data.get('email'))
return user
The Customer model will need a first_name and last_name field instead of name now.
Your current code (store view) will then work as well.

Get inputs from user into profile model of Django

I have a registration form which is an extension of UserCreationForm and I have a UserProfileForm. I am rendering both the forms to the same html during user registration.
The problem is, inputs are getting saved to the inbuilt users model but not to the Profile Model. No data is showing up in Profile Model.
I have tried many ways and looked for many solution but unable to find the mistake.
My forms.py looks like this -
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
username = forms.CharField(required=True)
class Meta:
model = User
fields = ['username',
'first_name',
'last_name',
'email',
'password1',
'password2'
]
def save(self,commit):
user = super(RegistrationForm,self).save(commit=False)
if commit:
user.save()
return user
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = ['user']
def save(self,commit):
user = super(RegistrationForm,self).save(commit=False)
USN =self.cleaned_data['USN']
year = self.cleaned_data['year']
sem = super(RegistrationForm,self).save(commit=False)
if commit:
user.save()
return user
Have created UserProfile model in models.py
class UserProfile(models.Model):
alphanumeric = RegexValidator(r'^[0-9A-Z]*$', 'Only alphanumeric
characters are allowed.')
user = models.OneToOneField(User, related_name =
'profile',on_delete=models.CASCADE)
USN = models.CharField(max_length=50, blank=True, null=True, validators=
[alphanumeric])
year = models.IntegerField(default=0)
sem = models.IntegerField(default=0)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
objects=models.Manager()
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender = User)
I have used both the forms in Views.py -
def register(request):
if request.method == 'POST':
form_1 = RegistrationForm(request.POST)
form_2 = UserProfileForm(request.POST)
if form_1.is_valid() and form_2.is_valid():
save_1 = form_1.save(commit = False)
save_2 = form_1.save(commit = False)
save_1.save()
save_2.save()
return render(request,'main/home.html')
else:
form_1 = RegistrationForm()
form_2 = UserProfileForm()
args = {'form_1':form_1,'form_2':form_2}
return render(request, 'account/register.html',args)
The username in the profile model object shows correctly, but other fields are not getting updated. I want other fields also getting updated in the profile object.

Trying to extend User to UserProfile in form Django

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

OSError when trying to register in Django

I am trying to submit 2 forms at a time to create my student user in Django. I have been struggling for a while now, but I think I'm finally closing to an end on how to manage 2 forms at a time for my users to register. But when I fill in the data from my view, I get the error:
[Errno 22] Invalid argument: "C:\\Users\\danny\\Desktop\\Projects\\bachelor_thesis\\eve\\templates\\{'form1': <UserForm bound=False, valid=Unknown, fields=(username;email;first_name;last_name;password)>, 'form2': <StudentForm bound=False, valid=Unknown, fields=(phone;student_ID;photo)>}"
Here are my files:
#csrf_protect
def student_register(request):
if request.method == 'POST':
form1 = UserForm(request.POST, prefix="user")
form2 = StudentForm(request.POST, prefix="profile")
if form1.is_valid() and form2.is_valid():
# create initial entry for user
username = form1.cleaned_data["username"]
password = form1.cleaned_data["password"]
new_user = User.objects.create_user(username, password)
new_user.save()
# create entry for UserProfile (extension of new_user object)
profile = form2.save(commit=False)
profile.user = new_user
profile.save()
return HttpResponseRedirect("index")
else:
form1 = UserForm(prefix="user")
form2 = StudentForm(prefix="profile")
c = {
'form1': form1,
'form2': form2,
}
c.update(request)
return render(request, "student_signup_form.html", c)
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name', 'password')
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('phone', 'student_ID', 'photo')
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')])
photo = models.ImageField(upload_to='students_images')
phone = models.CharField(max_length=15, )
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_student(sender, instance, created, **kwargs):
if created:
Student.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_student(sender, instance, **kwargs):
instance.profile.save()
Also, when I open registration form, password is seeable. Also, how do I add a confirmation password fields? Thanks.
Here is the traceback: https://pastebin.com/b90muPZY
This issue is bothering me for a while.

Django extra registration details not saving

I have form.py with class RegistrationForm and everything works fine but the extra details like email, first and last name, roles is not saved to my account/User profiles but first and last name + emails is saved under AUTHENTICATION AND AUTHORIZATION/Users
I been trying to figure our if I made some mix up with model, form or views.
What could be the problem? Using python 3 with latest django
2nd
3rd
Models.py
class UserProfile(models.Model):
STUDENT = 1
TOURIST = 2
BUSINESS = 3
ADMIN = 4
ROLE_CHOICES = (
(STUDENT, 'Student'),
(TOURIST, 'Tourist'),
(BUSINESS, 'Business'),
(ADMIN, 'Admin'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
# first_name = models.CharField(max_length=100, default='')
# last_name = models.CharField(max_length=100, default='')
email = models.EmailField()
phone = models.IntegerField(default=0)
image = models.ImageField(upload_to='image_profile', blank=True)
role = models.PositiveSmallIntegerField(choices=ROLE_CHOICES, null=True, blank=True)
# admin = UserProfileManager()
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
forms.py
ROLES = ((0, 'Student'), (1, 'Tourist'), (2, 'Business'))
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
role = forms.ChoiceField(choices=ROLES)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'role',
'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.role = self.cleaned_data['role']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Your account has been created!')
return redirect(reverse('city:home'))
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'account/register_form.html', args)
Admin.py
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'role', 'email')
def user_info(self, obj):
return obj.role
def get_queryset(self, request):
queryset = super(UserProfileAdmin, self).get_queryset(request)
queryset = queryset.order_by('email')
return queryset
role.short_description = 'User Type'
admin.site.register(UserProfile, UserProfileAdmin)
By given screen shots i think you are using allauth library. If you want to use allauth and modify user model then you have to import AbstractUser class of allauth
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(_('Telephone'), blank=True, max_length=20)
address = models.CharField(_('Address'), blank=True, max_length=255)

Categories

Resources