I have the User customize model to several roles or users types such as:
- Student user
- Professor User
- Executive User
My User model is of this way:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=40, unique=True)
slug = models.SlugField(
max_length=100,
blank=True
)
is_student = models.BooleanField(
default=False,
verbose_name='Student',
help_text='Student profile'
)
is_professor = models.BooleanField(
default=False,
verbose_name='Professor',
help_text='Professor profile'
)
is_executive = models.BooleanField(
default=False,
verbose_name='Executive',
help_text='Executive profile',
)
other fields ...
I have some functions into my User model too, which let me get the profiles according to user type:
def get_student_profile(self):
student_profile = None
if hasattr(self, 'studentprofile'):
student_profile = self.studentprofile
return student_profile
def get_professor_profile(self):
professor_profile = None
if hasattr(self, 'professorprofile'):
professor_profile = self.professorprofile
return professor_profile
def get_executive_profile(self):
executive_profile = None
if hasattr(self, 'executiveprofile'):
executive_profile = self.executiveprofile
return executive_profile
# This method does not works. It's illustrative
# How to get the user profile in this view for send data?
def get_user_profile(self):
user_profile = None
if hasattr(self, 'user'):
user_profile = self.user
return user_profile
def save(self, *args, **kwargs):
user = super(User,self).save(*args,**kwargs)
# Creating an user with student profile
if self.is_student and not StudentProfile.objects.filter(user=self).exists():
student_profile = StudentProfile(user = self)
student_slug = self.username
student_profile.slug = student_slug
student_profile.save()
# Creating an user with professor profile
elif self.is_professor and not ProfessorProfile.objects.filter(user=self).exists():
professor_profile = ProfessorProfile(user=self)
professor_slug = self.username
professor_profile.slug = professor_slug
professor_profile.save()
# Creating an user with executive profile
elif self.is_executive and not ExecutiveProfile.objects.filter(user=self).exists():
executive_profile = ExecutiveProfile(user = self)
executive_slug = self.username
executive_profile.slug = executive_slug
executive_profile.save()
# I have this signal to get the username and assign to slug field
@receiver(post_save, sender=User)
def post_save_user(sender, instance, **kwargs):
slug = slugify(instance.username)
User.objects.filter(pk=instance.pk).update(slug=slug)
Each profile (Student
, Professor
and Executive
) is managed in their own model with their own fields:
class StudentProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
class ProfessorProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
class ExecutiveProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
In my authentication process, I've set LOGIN_REDIRECT_URL = 'dashboard'
attribute, in my settings, and I have a DashboardProfileView
class which ask for profile users when these are Students or Professors or Executives of this way:
class DashboardProfileView(LoginRequiredMixin, TemplateView):
template_name = 'dashboard.html'
def get_context_data(self, **kwargs):
context = super(DashboardProfileView, self).get_context_data(**kwargs)
user = self.request.user
if user.is_student:
profile = user.get_student_profile()
context['userprofile'] = profile
elif user.is_professor:
profile = user.get_professor_profile()
context['userprofile'] = profile
elif user.is_executive:
profile = user.get_executive_profile()
context['userprofile'] = profile
elif user.is_study_host:
profile = user.get_study_host_profile()
context['userprofile'] = profile
elif user.is_active:
profile = user.get_user_profile()
context['userprofile'] = profile
return context
My DashboardProfileView
class works well, when the user authenticated have is_student
, or is_professor
or is_executive
attribute.
But when I create and user without any of these attributes (is_student
, or is_professor
or is_executive
) the user profile context in my DashboardProfileView
is not sent to the template, reason which I do not get the values profile of an user.
As the user does not have attribute profile, I ask of this way in the view:
if user.is_active:
profile = user.get_user_profile()
context['userprofile'] = profile
Due to that all users created have is_active boolean attribute set to True, but this does not work.
How to can I get the user profile in my view when the user is not is_student, is not is_professor and is not is_executive, this mean, is only a normal django user?
UPDATE
According to the @Sijan Bhandari answer it's true, context['userprofile'] = self.request.user
is the suited way of ask for the normal user profile. This should works.
But with these suited change in my base template I have a NoReverseMatch
problem in some of my urls and it this:
File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/urls/resolvers.py", line 392, in _reverse_with_prefix
(lookup_view_s, args, kwargs, len(patterns), patterns)
django.urls.exceptions.NoReverseMatch: Reverse for 'preferences' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['accounts/preferences/(?P<slug>[\\w\\-]+)/$']
[07/Apr/2017 11:52:26] "GET /dashboard/ HTTP/1.1" 500 179440
dashboard/
it's the URL to redirect when the user is signin.
url(r'^dashboard/', DashboardProfileView.as_view(), name='dashboard'),
But the problem it's when the system try render accounts/preferences/username
URL, which is created to view the account options to all users without matter their user type.
In my urls.py y have two urls accounts/
url(r'^accounts/', include('accounts.urls', namespace = 'accounts')),
# Call the accounts/urls.py to other urls like preferences/
url(r'^accounts/', include('django.contrib.auth.urls'), name='login'),
# I don't assign namespace because this is django URL to pre-bult-in login function
In my accounts/urls.py I have the preferences/
URL:
url(r"^preferences/(?P<slug>[\w\-]+)/$",
views.AccountSettingsUpdateView.as_view(),
name='preferences'
),
Here, I am telling that request a user with the slug
field which make reference their username
field. I pass in this URL the slug of user to retrieve their account data and I want that this regular expression let me alphanumeric characters in uppercase and lowercase and hypen and underscores
Then in my template, I put this url of this way:
<li><a href="{% url 'accounts:preferences' userprofile.user.username %}">Settings</a></li>
But when I sign in process with some user which does not have the (is_student
, is_professor
, is_executive
) profiles, this mean a django normal user, I have the following behavior:
File "/home/bgarcial/.virtualenvs/ihost/lib/python3.5/site-packages/django/urls/resolvers.py", line 392, in _reverse_with_prefix
(lookup_view_s, args, kwargs, len(patterns), patterns)
django.urls.exceptions.NoReverseMatch: Reverse for 'preferences' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['accounts/preferences/(?P<slug>[\\w\\-]+)/$']
[07/Apr/2017 12:12:18] "GET /dashboard/ HTTP/1.1" 500 179440