Search code examples
djangotemplatesprofiledjango-context

get_profile() fails randomly in Django project


In my Django project I have a user authentication system. Each user has a userprofile:

# Extending main user profile
class UserProfile(models.Model):
    # Required
    user = models.OneToOneField(User)

    # Added fields to main user model
    position = models.CharField(max_length=20, null=True, blank=True)
    avatar = models.ImageField(upload_to=upload_path_handler, blank=True, default='images/avatar.png')

class Meta:
    app_label = 'auth'

# handler --  Create automatically UserProfile foreign key when
# a new user is registered.
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        # Creating UserProfile
        UserProfile.objects.create(user=instance)

post_save.connect(create_user_profile, sender=User)

Well, I have a context_processor.py which its main function returns something like this:

return {'USER_MEDIA_URL': settings.USER_MEDIA_URL,
'DEBUG': settings.DEBUG,
'SITE_URL': settings.SITE_URL,
'keys_left': keys_left,
'ownRoom': c,
'userThumbnail': request.user.get_profile().avatar,}

All my templates use "userThumbnail" and "request.user.get_profile().avatar" fails randomly without any kind of explication.

The returned error in template is:

Unable to load the profile model, check AUTH_PROFILE_MODULE in your project settings

Sometimes I get this error and sometimes not. It's very annoying.

Any hint?


Solution

  • It's very annoying.

    :)

    If you don't need to perform other extra tasks on post_save except of creating a profile, maybe you could use AutoOneToOneField from django-annoying instead?

    The method get_profile() does not create the profile, if it does not exist. (django docs)

    AutoOneToOneField does.

    It's not really an answer, but it may turn out to be a solution for you.

    from annoying.fields import AutoOneToOneField
    
    class UserProfile(models.Model):
    
        user = AutoOneToOneField(User, verbose_name=_(u"user"),
                                 on_delete=models.CASCADE,
                                 related_name="profile")
    

    Then you use it with something like that:

    return { 'userThumbnail': request.user.profile.avatar, }