0

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:

enter image description here

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
Community
  • 1
  • 1
bgarcial
  • 2,915
  • 10
  • 56
  • 123
  • 1
    Why did you call the get_user_profile(), if that is the normal user? I mean you can simply assign ```context['userprofile'] = self.request.user```, right? – Sijan Bhandari Apr 07 '17 at 04:37
  • @SijanBhandari thanks for your support, I think that `self.request.user` it's the suited way. But I now have some difficult in some of my URLs. Can check you my **UPDATE** in my question please. My apologies for the inconcenience. – bgarcial Apr 07 '17 at 12:18
  • 1
    The error is raising due to the url pattern you provides in the template. What is the url for preferences ? Here is what I have used . ```url(r'^tags/(?P.+)/$', views.tags, name='tags')``` in template change your url tag to: ```{% url "tags" slug=i.slug %}``` – Sijan Bhandari Apr 07 '17 at 13:54
  • @SijanBhandari I've fixed my URL `preferences/` I had type other url. But I don't understand in my template what type ... the error follow appearing. My apologies. – bgarcial Apr 07 '17 at 14:14
  • 1
    How did you send the user parameter in the url? {% url "accounts:preferences" username=userprofile.user.username %} And, 'username' should in the url for parsing slug. – Sijan Bhandari Apr 07 '17 at 15:29
  • @SijanBhandari The parameter in the url I am sending of this way: `url(r"^preferences/(?P[\w\-]+)/$", views.AccountSettingsUpdateView.as_view(), name='preferences' ),` I try like you tell me `/(?P.+)/$'` but of this way in some navigation the url's were concatenated in my browser and break the application. – bgarcial Apr 07 '17 at 15:56
  • @SijanBhandari I don't understand when you tell me **And, 'username' should in the url for parsing slug** my apologies. – bgarcial May 16 '17 at 20:16

0 Answers0