How Do I Create a User Profile Update View/Form? - python

I trying to update the user profile but I can't get that what mistake I do here.
#forms.py
class AddStudentUserForm(forms.ModelForm):
class Meta:
model = User
fields = ["username", "first_name", "last_name"]
class AddStudentStaffForm(forms.ModelForm):
class Meta:
model = Staff
fields = ["gender", "dob", "mob", "img"]
#views.py
def editProfile(request, user, id):
if request.POST:
staffform = AddStudentStaffForm(request.POST or None, request.FILES or None, instance=request.user.staff_profile)
userform = AddStudentUserForm(data=request.POST, instance=request.user)
if staffform.is_valid():
staffform.save()
if userform.is_valid():
userform.save()
return redirect(profile,user)
return render(request, 'edit.html')
#models.py
class Staff(models.Model):
Male = 'Male'
Female = 'Female'
Other = 'Other'
GENDER_CHOICE = (
(Male, 'Male'),
(Female, 'Female'),
(Other, 'Other')
)
id = models.AutoField(primary_key=True)
admin = models.OneToOneField(User, related_name='staff_profile', on_delete=models.CASCADE)
gender = models.CharField(max_length=10, choices=GENDER_CHOICE, default=Male)
dob = models.DateField(auto_now_add=False, blank=True, null=True, default=None)
mob = models.IntegerField(blank=True, null=True, default=None)
img = models.ImageField(upload_to='staff/', blank="True", null="True")
objects = models.Manager()
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Staff.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.staff_profile.save()
def __str__(self):
return self.gender
I started to create a Student Management System project. But I faced some difficulties to develop it. I trying lot of to solve these problem but since I can't solve that.
Here if I want to update the Staff model fields like gender, dob, mob it will updated successfully but when I trying to update the User model fields like username, first_name, last_name it will not update. I think the if userform.is_valid(): condition couldn't run, but I can't get what mistake I do here.

You can debug why the form is not valid, try code below :
if userform.is_valid():
userform.save()
return redirect(profile,user)
else:
print userform.errors #To see the form errors in the console.

Related

Django signals for user profile (Customer and Employee)

I am trying to create a signal to create a profile for a newly created user. However, I need to have two different types of profiles: A customer profile and an employee profile. The type of profile which will be created is decided inside my User model via the "user_type" field:
user/models.py:
class User(AbstractBaseUser):
USER_TYPES = (
('Employee', 'employee'),
('Customer', 'customer'),
('Vendor', 'vendor')
)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
phone_number = models.CharField(max_length=20)
user_type = models.CharField(max_length=8, choices=USER_TYPES)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
def __str__(self):
return f'{self.first_name} {self.last_name} : {self.email}'
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
# if user.is_employee == True
class EmployeeProfile(models.Model):
EMPLOYEE_ROLES = (
('Driver', 'driver'),
('Production', 'production'),
('Manager', 'manger')
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=12, choices=EMPLOYEE_ROLES)
def __str__(self):
return str(self.user)
# if user.is_customer == True
class CustomerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
company = models.CharField(max_length=100, null=True)
address = models.CharField(max_length=100, null=True)
address_2 = models.CharField(max_length=100, null=True)
city = models.CharField(max_length=50, null=True)
state = models.CharField(max_length=2, help_text="State Abbreviation (ex: OH)", null=True)
zipcode = models.CharField(max_length=5, null=True)
def __str__(self):
return str(self.user)
and then in my user/signals.py file:
#receiver(post_save, sender=User)
def create_customer_profile(sender, instance, created, **kwargs):
if created:
if User.user_type == 'customer':
CustomerProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def create_employee_profile(sender, instance, created, **kwargs):
if created:
if User.user_type == 'employee':
EmployeeProfile.objects.create(user=instance)
#receiver(post_save, sender=User, dispatch_uid='save_new_user_profile')
def save_profile(sender, instance, created, **kwargs):
user = instance
if created:
if User.user_type == 'customer':
customer_profile = CustomerProfile(user=user)
customer_profile.save()
if created:
if User.user_type == 'employee':
employee_profile = EmployeeProfile(user=user)
employee_profile.save()
When I create a user, no profiles are created. I was able to get a profile created by just using one Profile model and the standard signal:
#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()
... but ideally I want to have two separate profiles depending on the type of user that is created.
You can do this by overriding the save method from the User model.
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.user_type == 'customer':
CustomerProfile.objects.create(user=self)
elif self.user_type == 'employee':
EmployeeProfile.objects.create(user=self)

Serializer for creation of user profile in Django Rest Framework

I am trying to update the user profile in django rest framework
So i am able to create the user profile simultaneously with user creation using signals
Now i am trying to update the profile created:-
//models.py
class User(AbstractBaseUser,PermissionsMixin):
phone_regex=RegexValidator(regex = r'^[6-9]\d{9}$',message='please enter the correct phonenumber')
#name_regex=RegexValidator(regex=r'/^[A-Za-z]+$/',message='Please enter the correct name')
phone=models.CharField(validators=[phone_regex],max_length=15,unique=True)
date_joined=models.DateTimeField(verbose_name='date joined',auto_now_add=True)
last_login=models.DateTimeField(verbose_name='last login',auto_now=True)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False) # a admin user; non super-user
admin = models.BooleanField(default=False)
first_login=models.BooleanField(default=True)
USERNAME_FIELD='phone'
REQUIRED_FIELDS = []
class UserProfile(models.Model):
# There is an inherent relationship between the Profile and
# User models. By creating a one-to-one relationship between the two, we
# are formalizing this relationship. Every user will have one -- and only
# one -- related Profile model.
GENDER = (
('M', 'Homme'),
('F', 'Femme'),
)
user = models.OneToOneField(
User,related_name="profile", on_delete=models.CASCADE
)
# Each user profile will have a field where they can tell other users
# something about themselves. This field will be empty when the user
# creates their account, so we specify blank=True.
email=models.EmailField(unique=True,validators=[validate_email],max_length=254,blank=True,null=True)
name=models.CharField(max_length=15,blank=True)
dateofbirth=models.DateField(auto_now=False, null=True, blank=True)
Gender=models.CharField(max_length=1, choices=GENDER,blank=True,null=True)
address1 = models.CharField(
"Address",
max_length=1024,
blank=True,
null=True
)
address2 = models.CharField(
"Society",
max_length=1024,
blank=True,
null=True
)
address3 = models.CharField(
"Landmark",
max_length=1024,
blank=True,
null=True
)
zip_code = models.CharField(
"ZIP / Postal code",
max_length=12,
blank=True,
null=True
)
city = models.CharField(
"City",
max_length=1024,
default ="Gurugram",
blank=True,
null=True
)
country = models.CharField(
"Country",
max_length=10,
default="India",
blank=True,
null=True
)
# In addition to the `bio` field, each user may have a profile image or
# avatar. This field is not required and it may be blank.
# A timestamp representing when this object was created.
created_at = models.DateTimeField(auto_now_add=True,blank=True)
# A timestamp representing when this object was last updated.
updated_at = models.DateTimeField(auto_now=True,blank=True)
def __str__(self):
return self.user.phone
#receiver(post_save, sender=User)
def create_profile_for_user(sender, instance=None, created=False, **kargs):
if created:
UserProfile.objects.get_or_create(user=instance)
// Serializer.py
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields=("name",)
class UserSerializer(serializers.ModelSerializer):
user = UserProfileSerializer(many=True)
class Meta:
model = User
fields = ('user', 'phone',)
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
profile = user_data.objects.create(user=user, **validated_data)
return profile
def update(self, instance, validated_data):
print("update function")
# profile_data = validated_data.pop('profile')
# print(profile_data)
profile_data = validated_data.pop('user')
profile = instance.profile
# print("profile is ",profile)
print(profile_data.name)
print("name in validation ",validated_data['name'], " type is ",print(type(validated_data)))
instance.username = validated_data.get('name', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.save()
print("name is ",instance.profile.name )
#profile.Gender = validated_data['Gender'],
#profile.email = validated_data['email'],
#profile.dateofbirth=validated_data['dateofbirth'],
#profile.address1=validated_data['address1'],
##profile.address2=validated_data['address2'],
#profile.address3=validated_data['address3']
# print("1",profile)
#print(profile.Gender)
#print(profile.email)
#print(profile.dateofbirth)
profile.save()
print("2",profile)
print(profile.name)
print("save done")
return instance
//views.py
class ProfileCreateAPIView(CreateAPIView):
def put(self, request, *args, **kwargs):
print("my print 0",request)
header_token = request.META.get('HTTP_AUTHORIZATION', None)
print(header_token)
access_token=header_token.split(' ')[1]
status,user =validate_token(access_token)
print(request.data)
user_profile_serializer = UserProfileSerializer(
instance=user,
data=request.data
)
user_serializer = UserSerializer(
instance=user,
data=request.data)
print("my print 1",user_profile_serializer.is_valid())
print("my print 2",user_serializer.is_valid())
if user_profile_serializer.is_valid() and user_serializer.is_valid():
user_profile_serializer.save()
print("user_profile save done")
user_serializer.save()
print("user save done")
return Response(
status=rt_status.HTTP_200_OK)
# Combine errors from both serializers.
# errors = dict()
# errors.update(user_profile_serializer.errors)
#errors.update(user_serializer.errors)
else:
return Response(status=rt_status.HTTP_400_BAD_REQUEST)
'''
return Response(status=rt_status.HTTP_400_BAD_REQUEST)
'''
Now the issue is when i am hitting the api I am getting user_serializer.is_valid() as TRUE but False from UserProfile.
I feel there is some issue with my getting the profile data.
But I am not able to understand how to resolve the issue .
Any help is much appreciated.

RelatedObjectDoesNotExist at /rest-auth/user/: User has no userprofile

I am trying to update UserDetailsSerializer and the problem is when I run my code in my test model it works but when I use it in my actual app, it throws this error: 'User' object has no attribute 'userprofile'
model.py
class userProfileModel(models.Model):
GENDER = [
('', ""),
('M', "Male"),
('F', "Female")
]
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='userprofile', default='')
avatar = models.ImageField(upload_to='avatar/', default='avatar/no-avatar.png')
age = models.DateField(auto_now_add=True)
gender = models.CharField(max_length=10, choices=GENDER, default='')
address = models.CharField(max_length=500, default='')
longitude = models.FloatField(default=0.0)
latitude = models.FloatField(default=0.0)
phone = models.IntegerField(default=0)
user_is_active = models.BooleanField(default=False)
def __str__(self):
return self.user.username
serializers.py
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = userProfileModel
fields = (
'id',
'avatar',
'age',
'gender',
'address',
'longitude',
'latitude',
'phone',
)
class UserDetailsSerializer(UserDetailsSerializer):
profile = UserProfileSerializer(source='userprofile')
class Meta(UserDetailsSerializer.Meta):
fields = UserDetailsSerializer.Meta.fields + ('profile',)
read_only_fields = ('',)
def update(self, instance, validated_data):
# User data
nested_serializer = self.fields['profile']
nested_instance = instance.userprofile
nested_data = validated_data.pop('userprofile')
nested_serializer.update(nested_instance, nested_data)
return super(UserDetailsSerializer, self).update(instance, validated_data)
The error:
RelatedObjectDoesNotExist at /rest-auth/user/
User has no userprofile.
It's because UserProfile instance for user is not created yet. You can use a signal on post_save of User model, so that whenever user is saved, check if UserProfile instance for it is created, if not then create one. like below:
def create_profile(sender,**kwargs ):
if kwargs['created']:
user_profile=UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile,sender=User)
Also like my friend suggested in comments, Always check if userProfile instance is exist with hasattr(instance, 'profile'), if not then create a default one for that user.
Reference: This is a cool topic Extending user model
When you are creating user profile, make sure you save them, you can refer this snippet.
class Profile(models.Model):
# ...
#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()
And also don't forget to import post_save.

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)

Categories

Resources