I have a custom users schema in Django for work with roles or users type, creating an application named userprofile which will be or will setup my custom user model.
In my settings.py I have the following configuration:
INSTALLED_APPS = [
...
'userprofile',
]
#Custom model Users
AUTH_USER_MODEL = 'userprofile.User'
I customize my User class (userprofile/models.py) that inherit of the AbstractUser class for add some fields to my User model due to my requirements demanded me.
I also create these another models for roles/profile users (MedicalProfile, PatientProfile, PhysiotherapistProfile
) with their own fields or attributes
In addition MedicalProfile, PatientProfile, PhysiotherapistProfile
have a OneToOneField relationship with my custom model/class User
so:
from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
#from django.contrib.auth import get_user_model
from django.dispatch import receiver
from django.db.models.signals import post_save
# Extending Django's default User
# https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#extending-django-s-default-user
# We inherit from AbstractUser class to add some fields/attibutes to our user model
# https://github.com/django/django/blob/master/django/contrib/auth/models.py#L297
# Differentes between AbstractUser and AbstractBaseUser
# http://stackoverflow.com/questions/21514354/difference-between-abstractuser-and-abstractbaseuser-in-django
class User(AbstractUser):
is_medical = models.BooleanField(default=False)
is_physiotherapist = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
slug = models.SlugField(max_length=100, blank=True)
photo = models.ImageField(upload_to='avatars', null = True, blank = True)
# We get the profiles user according with their type
def get_medical_profile(self):
medical_profile = None
if hasattr(self, 'medicalprofile'):
medical_profile=self.medicalprofile
return medical_profile
def get_patient_profile(self):
patient_profile = None
if hasattr(self, 'patientprofile'):
patient_profile = self.patientprofile
return patient_profile
def get_physiotherapist_profile(self):
physiotherapist_profile = None
if hasattr(self, 'physiotherapistprofile'):
physiotherapist_profile = self.physiotherapistprofile
return physiotherapist_profile
# We redefine the attributes (create db_table attribute) in class Meta to say to Django
# that users will save in the same table that the Django default user model
# https://github.com/django/django/blob/master/django/contrib/auth/models.py#L343
class Meta:
db_table = 'auth_user'
class MedicalProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
#active = models.BooleanField(default=True)
name = models.CharField(max_length=64)
class PatientProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
#active = models.BooleanField(default=True)
name = models.CharField(max_length=64)
class PhysiotherapistProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
#active = models.BooleanField(default=True)
name = models.CharField(max_length=64)
"""
So we’re defined a signal for the User model, that is triggered every time a User instance is saved
The arguments used in the create_profile_for_new_user are:
sender: the User model class
created: a boolean indicating if a new User has been created
instance: the User instance being saved
"""
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
#def create_profile_for_new_user(sender, instance, created, **kwargs):
def create_profile_for_new_user(sender, instance, created, **kwargs):
user = instance
# ----------------- Begin debug----------------------
import ipdb
#ipdb.set_trace()
#------------------------
if created:
#ipdb.set_trace()
if user.is_medical:
ipdb.set_trace()
profile=MedicalProfile(user=instance)
profile.save()
"""
This signal checks if a new instance of the User model has been created,
and if true, it creates a Profile instance with using the new user instance.
"""
My Question
I want to focus my question in relation about of the post_save signal operation, this mean in the create_profile_for_new_user()
method:
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_profile_for_new_user(sender, instance, created, **kwargs):
user = instance
# ----------------- Begin debug----------------------
import ipdb
#------------------------
if created:
if user.is_medical:
ipdb.set_trace()
profile=MedicalProfile(user=instance)
profile.save()
I want, each that an user is created, automatically (by post_save signal action) be created their profile (MedicalProfile, PatientProfile, PhysiotherapistProfile) according to if their field checked (is_medical, is_patient, is_physiotherapist) at the User class (same black image presented above)
The inconvenient that I have is with my signal, and it's the following:
I have been checking the situation through ipdb basic debug functions and I think so that when I create the user the compiler or the steps don't arrive to the section when I check if my user is medical (if user.is_medical code line) such as follow:
1. I've placed a debug point initially of this way:
In the code section in where the user instance that has been created is sent
I go to my Django admin and I create a new user and when press click in "Save" (first moment to user create):
3. When I press "Save" button, the debug point enter to action
Then, I check the value of the variables that accord to my function which I am applying the signal are defined until the moment and they are inside the debug process. They are:
sender
, created
, instance
(this mean, the parameters of the function)user
, that is the same instance variableThe above,denote that the parameters are arriving. All is O.K for the moment.
It's true the sender, instance and created parameters are arriving and when check for the is_medical
attribute (boolean) which depend that the profile be saved in MedicalProfile model, I get this:
My attribute is_medical
have the boolean value as False
and I think that I can understand it, because we know that the user creation is divided in two sequentials phases in the django admin
And, is in that same phase in which I tell to Django that my user will be or will have the medical profile, checking the is_medical
checkbox attribute
I think that when the user is saved in the first phase (I allocate only username and password) the is_medical checkbox not yet is setup (checked) and this is the reason by which their value is False
It's right?
set_trace()
point debug such as follow in the figure (red square):In this point, ipdb do not enter in action, my debug is not reached or does not work.
The signal action that is doing is create the new User, but not create the profile for the user, in this case, the MedicalProfile beacuse I checked the is_medical
checkbox when I was create the user. Just create the user and nothing more ...
I think that the is_medical
attribute never is True, despite that I checked via admin django form, ant these it's the condition for that my user instance be saved in MedicalProfile model. :(
All this, carry me to the following question:
What alternatives can I have for solve this situation and when I create an user, their profile instance be saved (MedicalProfile, PhysiotherapistProfile, PatientProfile) depending of the attribute checkbo/field (is_medical, is_physiotherapist , is_patient) that I choose?
I bring to all my apologies before, in case of the my question do not be suited or appropriated with the stackoverflow philosophy or by the extense of my question.
The reason that it's extense is that I want give all details for get an answer
Any orientation I will be grateful and will be appreciated
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/142d89ce-4f3b-4c5f-af7b-cd8a6ff90fea%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
save()
method of the AbstractUser
class, instead of apply the post_save()
signal to the create_profile_for_new_use
function.User
MedicalProfile
, PatientProfile
y PhisiotherapystProfile
models stayed so:
from __future__ import unicode_literals
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.template.defaultfilters import slugify
from django.dispatch import receiver
from django.db.models.signals import post_save
class User(AbstractUser):
is_medical = models.BooleanField(default=False)
is_physiotherapist = models.BooleanField(default=False)
is_patient = models.BooleanField(default=False)
slug = models.SlugField(max_length=100, blank=True)
photo = models.ImageField(upload_to='avatars', null = True, blank = True)
def save(self, *args, **kwargs):
user = super(User, self).save( *args, **kwargs)
# Creating and user with medical, patient and physiotherapist profiles
if self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
and self.is_patient and not PatientProfile.objects.filter(user=self).exists()\
and self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
medical_profile=MedicalProfile(user=self).save()
patient_profile=PatientProfile(user=self).save()
physiotherapist_profile=PhysiotherapistProfile(user=self).save()
#profile.save()
# Creating and user with medical and patient profiles
elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
and self.is_patient and not PatientProfile.objects.filter(user=self).exists():
medical_profile=MedicalProfile(user=self).save()
patient_profile=PatientProfile(user=self).save()
# Creating and user with medical and physiotherapist profiles
elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists()\
and self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
medical_profile=MedicalProfile(user=self).save()
physiotherapist_profile=PhysiotherapistProfile(user=self).save()
# Creating and user with physiotherapist and patient profiles
elif self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists()\
and self.is_patient and not PatientProfile.objects.filter(user=self).exists():
physiotherapist_profile = PhysiotherapistProfile(user=self).save()
patient_profile = PatientProfile(user=self).save()
# Creating and user with medical profile
elif self.is_medical and not MedicalProfile.objects.filter(user=self).exists():
profile = MedicalProfile(user=self)
profile.save()
# Creating and user with patient profile
elif self.is_patient and not PatientProfile.objects.filter(user=self).exists():
profile = PatientProfile(user=self)
profile.save()
# Creating and user with physiotherapist profiles
elif self.is_physiotherapist and not PhysiotherapistProfile.objects.filter(user=self).exists():
profile = PhysiotherapistProfile(user=self)
profile.save()
# Enter the username as slug field
@receiver(post_save, sender = settings.AUTH_USER_MODEL)
def post_save_user(sender, instance, **kwargs):
slug = slugify(instance.username)
User.objects.filter(pk=instance.pk).update(slug=slug)
...