I have a django project with the django-allauth app. I need to collect additional data from the user at signup. I came across a similar question here but unfortunately, no one answered the profile customization part.
Per the documentation provided for django-allauth:
ACCOUNT_SIGNUP_FORM_CLASS (=None)
A string pointing to a custom form class (e.g. ‘myapp.forms.SignupForm’) that is used during signup to ask the user for additional input (e.g. newsletter signup, birth date). This class should implement a ‘save’ method, accepting the newly signed up user as its only parameter.
I am new to django and am struggling with this. Can someone provide an example of such a custom form class? Do I need to add a model class as well with a link to the user object like this ?
Suppose you want to ask the user for his first/last name during signup. You'll need to put these fields in your own form, like so:
class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
Then, in your settings point to this form:
ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'
Note that SignupForm cannot be defined in the same file as form overrides through ACCOUNT_FORMS or SOCIALACCOUNT_FORMS, because that would lead to a circular import error.
That's all.
Using the solution suggested by pennersr I was getting a DeprecationWarning:
DeprecationWarning: The custom signup form must offer a def signup(self, request, user) method DeprecationWarning)
This is because as of version 0.15 the save method has been deprecated in favour of a def signup(request, user) method.
So to solve this, the code of the example should be like this:
class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
Here's what worked for me combining a few of the other answers (none of them are 100% complete and DRY).
In yourapp/forms.py:
from django.contrib.auth import get_user_model
from django import forms
class SignupForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['first_name', 'last_name']
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
And in settings.py:
ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.SignupForm'
This way it uses the model forms so that it's DRY, and uses the new def signup. I tried putting 'myproject.myapp.forms.SignupForm' but that resulted in a error somehow.
#Shreyas: The below solution may not be the cleanest, but it works. Please let me know if you have any suggestions to clean it up any further.
To add information that does not belong to the default user profile, first create a model in yourapp/models.py. Read the general django docs to learn more about it, but basicly:
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
organisation = models.CharField(organisation, max_length=100, blank=True)
Then create a form in yourapp/forms.py:
from django import forms
class SignupForm(forms.Form):
first_name = forms.CharField(max_length=30, label='Voornaam')
last_name = forms.CharField(max_length=30, label='Achternaam')
organisation = forms.CharField(max_length=20, label='organisation')
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
# Replace 'profile' below with the related_name on the OneToOneField linking back to the User model
up = user.profile
up.organisation = self.cleaned_data['organisation']
user.save()
up.save()
In your users/forms.py you put:
from django.contrib.auth import get_user_model
class SignupForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ['first_name', 'last_name']
def save(self, user):
user.save()
In settings.py you put:
ACCOUNT_SIGNUP_FORM_CLASS = 'users.forms.SignupForm'
In this way you don't break DRY principle by multiplicity User models fields definition.
I've tried many different tutorials and all of them is missing something, repeating unnecessary code or doing weird things, bellow follows my solution that joins all the options that I've found, it's working, I have already put it in production BUT it still not convincing me because I would expect to receive first_name and last_name inside the functions that I attached to Users create to avoid creating a profile inside the form but I couldn't, by the away I think it will help you.
Models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
nationality = models.CharField(max_length=2, choices=COUNTRIES)
gender = models.CharField(max_length=1, choices=GENDERS)
def __str__(self):
return self.user.first_name
#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()
Forms.py
class SignupForm(forms.ModelForm):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
class Meta:
model = Profile
fields = ('first_name', 'last_name', 'nationality', 'gender')
def signup(self, request, user):
# Save your user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
user.profile.nationality = self.cleaned_data['nationality']
user.profile.gender = self.cleaned_data['gender']
user.profile.save()
Settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'apps.profile.forms.SignupForm'
#models.py
from django.conf import settings
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
image = models.ImageField(default='users/default.png', upload_to='users')
fields = models.ForeignKey('Field' ,null=True ,on_delete=models.SET_NULL)
category = models.ForeignKey('Category' ,null=True ,on_delete=models.SET_NULL)
description = models.TextField()
interests = models.ManyToManyField('Interests')
...
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
...
def userprofile_receiver(sender, instance, created, *args, **kwargs):
if created:
userprofile = UserProfile.objects.create(user=instance)
else:
instance.userprofile.save()
post_save.connect(userprofile_receiver, sender=settings.AUTH_USER_MODEL)
#forms.py
class SignupForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
self.fields['first_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter first name'})
self.fields['last_name'].widget = forms.TextInput(attrs={'placeholder': 'Enter last name'})
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
interests = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, help_text="Choose your interests", queryset=Interests.objects.all())
image = forms.ImageField(help_text="Upload profile image ")
fields = forms.ChoiceField(help_text="Choose your fields ")
category = forms.ChoiceField(help_text="Choose your category")
class Meta:
model = UserProfile
fields = ('first_name', 'last_name', 'name', 'image', 'fields', 'category', 'description', 'phone', 'facebook', 'twitter', 'skype', 'site', 'address', 'interests' ,'biography')
widgets = {
...
'description': forms.TextInput(attrs={'placeholder': 'Your description'}),
'address': forms.TextInput(attrs={'placeholder': 'Enter address'}),
'biography': forms.TextInput(attrs={'placeholder': 'Enter biography'}),
....
}
def signup(self, request, user):
# Save your user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
user.userprofile.image = self.cleaned_data.get('image')
user.userprofile.fields = self.cleaned_data['fields']
user.userprofile.category = self.cleaned_data['category']
user.userprofile.description = self.cleaned_data['description']
interests = self.cleaned_data['interests']
user.userprofile.interests.set(interests)
user.userprofile.save()
# settings.py or base.py
ACCOUNT_SIGNUP_FORM_CLASS = 'nameApp.forms.SignupForm'
That is it. (:
Create a Profile Model with user as OneToOneField
class Profile(models.Model):
user = models.OneToOneField(User, verbose_name=_('user'), related_name='profiles')
first_name=models.CharField(_("First Name"), max_length=150)
last_name=models.CharField(_("Last Name"), max_length=150)
mugshot = ImageField(_('mugshot'), upload_to = upload_to, blank=True)
phone= models.CharField(_("Phone Number"), max_length=100)
security_question = models.ForeignKey(SecurityQuestion, related_name='security_question')
answer=models.CharField(_("Answer"), max_length=200)
recovery_number= models.CharField(_("Recovery Mobile Number"), max_length=100)
city=models.ForeignKey(City,related_name='city', blank=True, null=True, help_text=_('Select your City'))
location=models.ForeignKey(Country,related_name='location', blank=True, null=True, help_text=_('Select your Location'))
Related
How would I grab the 2nd form and add it to the first form then selectively not allow that user to login. In the Doctorwizard done function.
maybe add a variable status?
etc.
username,password,email,first_name,last_name,verified
views.py
from django.core.files.storage import FileSystemStorage
import os
from django.conf import settings
class DoctorWizard(SessionWizardView):
file_storage = FileSystemStorage(location=os.path.join(settings.MEDIA_ROOT, 'doctor'))
template_name = "registration/signup.html"
form_list = [SignUpForm,verify]
def done(self, form_list, **kwargs):
data=process_data(form_list)
return redirect('home')
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.')
class Meta:
model = Profile
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )
class verify(forms.Form):
verified = forms.ImageField(required=True)
class Meta:
model = Profile
fields = ('verified',)
models.py
class Profile(AbstractUser):
bio = models.TextField(max_length=100, blank=True)
phone_number = PhoneNumberField(max_length=25, region="US")
birth_date = models.DateField(blank = True, null = True)
is_doctor = models.BooleanField(default=False)
verified = models.ImageField(upload_to='media/doctor')
date_created = models.DateTimeField(auto_now_add=True)
avatar = models.ImageField(default='default.png', upload_to='')
def done(self, form_list, **kwargs):
process_data(form_list)
userCreate = form_list[0]
userCreate.save()
username = userCreate.cleaned_data.get('username')
raw_password = userCreate.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
if user:
user.verified=form_list[1].cleaned_data.get('verified')
user.is_doctor=True
user.is_active=False
user.save()
Just grab the user and access it's fields.
I've used as a model AbstractUser extended by custom fields, created form automatically by ModelForm. The problem is that, users except superuser cannot log in to system. I think it's reason, their passwords are not hashing. Where should I make it ? Here are my codes.
forms.py:
class CustomUserSignUpForm(ModelForm):
class Meta:
model = CustomUser
fields = ['username', 'password', 'user_image', 'role', 'branch', 'license_number', 'fin_number', 'first_name', 'last_name', 'patronymic', 'phone_number', 'email', 'voen_number', 'is_active']
views.py:
def sign_up(request):
if request.method == 'POST':
form = CustomUserSignUpForm(request.POST)
if form.is_valid():
form.save()
else:
form = CustomUserSignUpForm()
context = {
'form': form,
}
return render(request, 'sign_up.html', context)
models.py:
class CustomUser(AbstractUser):
patronymic = models.CharField(_('Ata adı'), max_length=150, blank=True)
role = models.ForeignKey(Role, on_delete=models.CASCADE, blank=True, null=True)
user_image = models.FileField(_('Profil şəkli'), upload_to='static/assets/images/user-images', blank=True)
branch = models.ForeignKey(Branch, on_delete=models.CASCADE, blank=True, null=True)
phone_number = models.CharField(_('Telefon'), max_length=20, blank=True)
voen_number = models.CharField(_('VÖEN'), max_length=30, blank=True)
fin_number = models.CharField(_('FİN'), max_length=20, blank=True)
license_number = models.CharField(_('Lisenziya'), max_length=40, blank=True)
def __str__(self):
return self.username
To define a function to hash that password, you must inherited save method for you user form
class CustomUserSignUpForm(forms.ModelForm):
............
def save(self, commit=True):
# Save the provided password in hashed format
user = super(CustomUserSignUpForm, self).save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
This override of ModelForm is better off, because:
I check if the user exists.
I Hash de password if the password is not encoded.
class UsuarioAdmin(admin.ModelAdmin):
...
def save_model(self, request, obj, form, change):
try:
user_database = USUARIO.objects.get(pk=obj.pk)
except Exception:
user_database = None
if user_database is None \
or not (check_password(form.data['password'], user_database.password)
or user_database.password == form.data['password']):
obj.password = make_password(obj.password)
else:
obj.password = user_database.password
super().save_model(request, obj, form, change)
I extended the Django AbstratUser so that users can use email to sign in and signup, these work perfectly. The problem I am facing, however, is that the extra information on the extended model is not storing the information in the database, even though the user gets created. Once I hit the submit button, the user and extended model get created, and while the user model stores the information, the extended model is always empty.
I have tried using both signals and #transaction_atomic, yet, I have not been able to figure it out. Maybe I am missing out something, I do not know.
Models.py
class Company(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
name= models.CharField(_('Company name'), max_length=250)
...
#more information
...
class Meta:
verbose_name = _('Company')
verbose_name_plural = _('Companies')
def __str__(self):
return self.name
forms.py
class CompanySignUpForm(CustomUserCreationForm):
name = forms.CharField(widget=TextInput(attrs={'placeholder': 'Company name'}))
...
#more fields
...
class Meta(CustomUserCreationForm.Meta):
model = User
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_company = True
user.save()
company = Company.objects.create(user=user)
company.name = self.cleaned_data.get('name')
...
#more information
...
return user
Views.py
def company_signup(request):
if request.method == 'POST':
form = CompanySignUpForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'accounts/templates/company_success.html')
else:
form = CompanySignUpForm()
return render(request, 'accounts/templates/company_signup.html', context={
'title': _('Create a Company Account'),
'form': form,
})
Edit:
Thanks to #Mandrup, I was able to extend his solution to fit my need.
forms.py
class CompanySignUpForm(CustomUserCreationForm):
name = forms.CharField(widget=TextInput(attrs={'placeholder': 'Company name'}))
number_of_employees = forms.CharField(widget=NumberInput(attrs={'placeholder': 'Number of employees'}))
phone = forms.CharField(widget=TextInput(attrs={'placeholder': 'Contact Number'}))
country = forms.ModelChoiceField(queryset=Country.objects.all(), required=True, empty_label="Country")
class Meta(CustomUserCreationForm.Meta):
model = User
#transaction.atomic
def save(self, commit=True):
user = super(CompanySignUpForm, self).save(commit=False)
if commit:
user.is_company = True
user.save()
name = self.cleaned_data.get('name')
number_of_employees = self.cleaned_data.get('number_of_employees')
phone = self.cleaned_data.get('phone')
country = self.cleaned_data.get('country')
company = Company(user=user, name=name, number_of_employees=number_of_employees, phone=phone, country=country)
company.save()
return user
Edit:
This worked for me when i tried to create an extended user profile. I changed it to fit your needs.
Model:
class Company(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
name= models.CharField(max_length=250)
...
#more information
...
def __str__(self):
return self.name
Form:
class RegisterUserForm(UserCreationForm):
class Meta:
model = User
fields = ["username", "email", "password1", "password2"]#add whatever fields you want to here
def save(self, commit=True):
user = super(RegisterUserForm, self).save(commit=False)
if commit:
user.save()
company = Company(user=user, name='Company name')
company.save()
return user
I have the model "Account" below:
class Account(models.Model):
email=models.EmailField(verbose_name="email", max_length=60, unique=True)
username=models.CharField(max_length=30, unique=True)
data_inscricao=models.DateTimeField(verbose_name='Data de Inscrição', auto_now_add=True)
ultimo_login=models.DateTimeField(verbose_name='ùltimo Login', auto_now_add=True)
def __str__(self):
return self.username
and this other "PersonalData"...
class PersonalData(models.Model):
id_user=models.OneToOneField(Account, on_delete=models.CASCADE)
nome_completo=models.CharField(max_length=56, unique=True, null=True)
email=models.EmailField(max_length=60, verbose_name="Email", unique=True, null=True)
cpf=models.CharField(max_length=14, unique=True, null=True, verbose_name="CPF")
rg=models.CharField(max_length=12, unique=True, null=True, verbose_name="RG")
idade=models.IntegerField(null=True)
data_nascimento=models.DateField(verbose_name="Data de Nascimento", null=True)
genero=models.CharField(max_length=8, choices=GENERO, null=True)
estado_civil=models.CharField(max_length=13, null=True, choices=ESTADO_CIVIL, verbose_name="Estado Civil")
def __str__(self):
return self.nome_completo
views.py
def cadastro_curriculo(request):
form = InsereDadosPessoais(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return redirect("vagas")
return render(request, "personal/curriculo.html", {'form': form,})
forms.py
class InsereDadosPessoais(forms.ModelForm):
class Meta:
model = PersonalData
fields = '__all__'
I'ld like PersonalData.id_user use by default the Account.username of the loged user and I don't know how do that.
Just to exemplify, In Django Admin, my PersonalData model allows me to choose the user, but I want it to happen automatically and not manually.
Can someone help me?
at admin.py add the admin class as per the docs
assign exclude as per the docs
exclude = ('user',)
and at save_model
def save_model(self, request, obj, form, change):
obj.user = request.user
super().save_model(request, obj, form, change)
Check docs here
If you want to add this to normal views
forms.py
class XXForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(XXForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
obj = super(XXForm, self).save(commit=False)
obj.user = self.user
if commit:
obj.save()
return obj
views.py
def xxview(request, *args, **kwargs): # your args
if request.POST:
#your stuff
form = XXForm(request.POST......., user=request.user)
else:
# your stuff
Check views here
I think you are Brazilian too :) Welcome! I learned this from this site.
models.py
from django.contrib.auth import User
class PersonalData(models.Model):
id_user = models.OneToOneField(User, on_delete=models.PROTECT, null=True, blank=True)
cpf = models.CharField(max_length=14, unique=True, null=True, verbose_name="CPF")
rg = models.CharField(max_length=12, unique=True, null=True, verbose_name="RG")
idade = models.IntegerField(null=True)
data_nascimento = models.DateField(verbose_name="Data de Nascimento", null=True)
genero = models.CharField(max_length=8, choices=GENERO, null=True)
estado_civil = models.CharField(max_length=13, null=True, choices=ESTADO_CIVIL, verbose_name="Estado Civil")
data_inscricao = models.DateTimeField(verbose_name='Data de Inscrição', auto_now_add=True)
ultimo_login = models.DateTimeField(verbose_name='ùltimo Login', auto_now_add=True)
def __str__(self):
return '{} {}'.format(id_user.first_name, id_user.last_name)
def save_model(self, request, obj, form, change):
if not obj.id_user:
# Only set added_by during the first save.
obj.id_user = request.user
super().save_model(request, obj, form, change)
admin.py
from .models import PersonalData
class PersonalDataAdmin(admin.ModelAdmin):
readonly_fields = ('id_user',)
admin.site.register(PersonalData, PersonalDataAdmin)
Important notes:
You don't have to create a field that saves the full name, Django itself can do it for you.
If you are going to use Django-Admin you can work with permissions within it by own User models. Click here and read a little about.
I recommend you use the built-in User model, it would look like this. Feel free to access my profile and get my contact information, I would be happy to help you with your project!
I'd suppose you have to make id_user field a foreign key to Account identifier which you should add to your model. In your described scenario id_user will "use" Account.username which is not obligated to be unique among all the users registered in the system. So, I suggest you to create an id field for Account and utilize it as a numeral identifier for that model.
Also, if I do not mistake, Django has an intrinsic User model which is intended for usage in such cases. Of course, you can extend that model for adding specific attributes.
I have a site where you can sign up to be either someone who uses the service(customer) or someone who provides the service(worker). I have created two profiles in models.py to represent each. They are both extremely similar for the most part as of right now. Both forms display properly when you go to them, and if you are signing up as a customer and press submit everything goes smoothly and a new user under will show up in "Customer profiles" at http://127.0.0.1:8000/admin/ . But if you try to sign up as a worker, the following error appears:
Exception Type: RelatedObjectDoesNotExist
Exception Value:
User has no workerprofile.
I do not understand this because as you will see in the code below i use customerprofile and it works fine, if I use workerprofile it crashes.
Views.py:
def signup_as_worker(request):
if request.method == 'POST':
form = WorkerSignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.workerprofile.birth_date = form.cleaned_data.get('birth_date')
user.workerprofile.university = form.cleaned_data.get('university')
user.save() # explicitly save custom fields not in User model
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user) # login user after signup
return redirect('home')
else:
form = WorkerSignUpForm()
return render(request, 'core/signup_as_worker.html', {'form': form})
def signup_as_customer(request):
if request.method == 'POST':
form = CustomerSignUpForm(request.POST)
if form.is_valid():
user = form.save()
user.refresh_from_db() # load the profile instance created by the signal
user.customerprofile.birth_date = form.cleaned_data.get('birth_date')
user.customerprofile.university = form.cleaned_data.get('university')
user.save() # explicitly save custom fields not in User model
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=user.username, password=raw_password)
login(request, user) # login user after signup
return redirect('home')
else:
form = CustomerSignUpForm()
return render(request, 'core/signup_as_customer.html', {'form': form})
forms.py:
class WorkerSignUpForm(UserCreationForm):
#birth_date and university fields need to be declared seperately because they are not apart of User:
birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
university = forms.CharField()
class Meta:
model = User
fields = ('username',
'email',
'first_name',
'last_name',
'birth_date',
'university',
'password1',
'password2', )
class CustomerSignUpForm(UserCreationForm):
#birth_date and university fields need to be declared seperately because they are not apart of User:
birth_date = forms.DateField(help_text='Required. Format: YYYY-MM-DD')
university = forms.CharField()
class Meta:
model = User
fields = ('username',
'email',
'first_name',
'last_name',
'birth_date',
'university',
'password1',
'password2', )
models.py:
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 WorkerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
university = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
role = models.CharField(max_length = 10, default = 'USER')
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_worker_profile(sender, instance, created, **kwargs):
if created:
WorkerProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_worker_profile(sender, instance, **kwargs):
instance.workerprofile.save()
class CustomerProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
university = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
role = models.CharField(max_length = 10, default = 'CUSTOMER')
needLaundryDone = models.BooleanField(default = False)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_worker_profile(sender, instance, created, **kwargs):
if created:
CustomerProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_worker_profile(sender, instance, **kwargs):
instance.customerprofile.save()
I do not understand what the problem is.
Your signal handler method names for both models are the same. You are practically redefining the methods therefore only the second set of methods are called. Rename your CustomerProfile handlers to create_customer_profile and save_customer_profile.