User Level Registration in Django - python

I am trying to create two user levels in Django. When they register, they will see a dropdown field where they can choose whether they are a customer or a driver.
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_driver = models.BooleanField(default=False)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
address = models.CharField(max_length=300)
contact_no = models.CharField(max_length=11)
profile_pic = models.ImageField(blank=True, null=True)
def __str__(self):
return self.user.username
views.py
def RegisterPage(request):
form = RegisterForm()
if request.method == "POST":
form = RegisterForm(request.POST)
if form.is_valid():
form.save()
context = {'form':form}
return render(request, 'accounts/register.html', context)
forms.py
from django.contrib.auth.forms import UserCreationForm
from .models import *
from django import forms
from django.db import transaction
class RegisterForm(UserCreationForm):
email = forms.EmailField()
first_name = forms.CharField(max_length=60)
last_name = forms.CharField(max_length=150)
address = forms.CharField(max_length=300)
contact_no = forms.CharField(max_length=11)
profile_pic = forms.ImageField(required=False)
LEVELS = (
('Customer', 'Customer'),
('Driver', 'Driver'),
)
user_level = forms.ChoiceField(choices=LEVELS)
class Meta(UserCreationForm.Meta):
model = User
fields = ['username', 'email', 'first_name', 'last_name',
'password1', 'password2', 'address', 'contact_no',
'profile_pic', 'user_level']
#transaction.atomic
def save(self, commit=True):
user = super().save(commit=False)
level = self.cleaned_data.get('user_level')
if level == 'Customer':
user.is_customer = True
if commit:
user.save()
elif level == 'Driver':
user.is_driver = True
if commit:
user.save()
profile = Profile.objects.create(user=user)
profile.address = self.cleaned_data.get('address')
profile.contact_no = self.cleaned_data.get('contact_no')
profile.profile_pic = self.cleaned_data.get('profile_pic')
profile.save()
return user
I have registered my user model to the Django settings already. My problem is that it doesn't save to the User model when I check it in the admin page. What seems to be the problem?

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.

Profile ID not stored in User after creation Django

I wrote the following code:
class RegisterForm(UserCreationForm):
email = forms.EmailField(max_length=200, help_text='Required')
class Meta:
model = CustomUser
fields = ('username', 'email', 'password1', 'password2')
#login_required(login_url="/login")
def index(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
profile = Profile().save()
user = form
user.profile = profile
user.save()
return redirect('users')
else:
print(form.errors)
else:
form = RegisterForm()
user_model = get_user_model()
users = user_model.objects.all()
paginator = Paginator(users, 15)
page = request.GET.get('page')
users = paginator.get_page(page)
return render(request, 'users/index.html', {'users': users, 'form': form})
class Profile(models.Model):
has_premium_until = models.DateTimeField(null=True, blank=True)
has_premium = models.BooleanField(default=False)
has_telegram_premium_until = models.DateTimeField(null=True, blank=True)
has_telegram_premium = models.BooleanField(default=False)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
class CustomUser(AbstractUser):
email = models.EmailField(max_length=255, unique=True)
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, null=True)
When I'm submitting the form the user as well as the profile is created but the profile is not stored in the user (the profile_id stays null).
Anyone who can help me out?
Change your code to
if form.is_valid():
profile = Profile().save()
user = form.save(commit=False)
user.profile = profile
user.save()
return redirect('users')
This way the user object will be created and then you refer to the profile ju just created and save it.
There is however another way of doing it with signals:
#receiver(models.signals.post_save, sender=CustomUser)
def create_profile_on_user_reg(sender, instance, created,**kwargs):
if created:
instance.profile = Profile()
instance.save()
Check out more on Django signals documentation

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.

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)

Django Admin - 'UserProfile' object has no attribute 'first_name'

I've tried a UserProfile using OneToOneField to extend User in Django which seems to work. Then, I've created a registration view and forms to be able to register new User using UserProfile module.
The problem is that when I've created a User using this form, Django Admin started to raise errors when I click on Users button in Admin page.
EDIT: Probably is worth to say that when I've created a new User, there were some exception that ID is not unique which is probably caused by post_save method in models.
Do you know where is the problem or what should I do?
Here are pieces of my code:
VIEWS.PY
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.password)
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})
FORMS.PY
class ContactUsForm(forms.Form):
contact_name = forms.CharField(required=True)
from_email = forms.EmailField(required=True)
subject = forms.CharField(required=True)
message = forms.CharField(
required=True,
widget=forms.Textarea
)
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('telephone',)
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)
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.first_name,self.surname)
def create_profile_user_callback(sender,instance, **kwargs):
profile, new = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile_user_callback, User)
ADMIN.PY
admin.site.register(AdminContact)
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'User_Profile'
class UserAdmin(BaseUserAdmin):
inlines = (UserProfileInline, )
admin.site.unregister(User)
admin.site.register(User,UserAdmin)
__unicode__ method, in your UserProfile model, it uses self.first_name and self.sur_name, which actually do not exist in this model.
self.user.first_name would be appropriate.
The problem is in your code..
def unicode(self):
return '{} {}'.format(self.first_name,self.surname)
here you call self.first_name,self.surname which in not define in UserProfile
define first_name and surname
like
first_name= models.CharField(max_length=255)
surname= models.CharField(max_length=255)
in your UserProfile class

Categories

Resources