Cody
Cody

Reputation: 2649

Django unable to access user profile data from User object

I have a Profile model like this:

class UserProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='profile')
    about = models.TextField()

When I try to access UserProfile data from User instance I get this error:

In [1]: 

In [1]: from django.contrib.auth.models import User

In [5]: u = User.objects.all()[0]

In [6]: u
Out[6]: <User: admin>

In [13]: u.profile
---------------------------------------------------------------------------
RelatedObjectDoesNotExist                 Traceback (most recent call last)
<ipython-input-13-679bed70444a> in <module>()
----> 1 u.profile

~/project/djangoedu/env/lib/python3.5/site-packages/django/db/models/fields/related_descriptors.py in __get__(self, instance, cls)
    402                 "%s has no %s." % (
    403                     instance.__class__.__name__,
--> 404                     self.related.get_accessor_name()
    405                 )
    406             )

RelatedObjectDoesNotExist: User has no profile.

In [14]: u.author
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-327f8c8449fd> in <module>()
----> 1 u.author

AttributeError: 'User' object has no attribute 'author'

In [15]: 

Upvotes: 0

Views: 338

Answers (3)

abdullah zulfiqar
abdullah zulfiqar

Reputation: 25

In Django models, when you create a relationship between two models using fields like ForeignKey or OneToOneField, Django automatically generates a reverse relationship to allow you to access related objects from the other side of the relationship. By default, Django generates a related name based on the name of the related model in lowercase.

However, you can customize this related name using the "related_name" attribute. In code below, I have set "related_name" to "profile" in the OneToOneField between the UserProfile and User models. This means that you can access the UserProfile instance associated with a User instance using the "profile" attribute.

For example, when you have a User instance called user, you can access their related UserProfile instance like this:

from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
    phone = models.CharField(max_length=21, default='', null=True, blank=True)
    postcode = models.CharField(max_length=11, default='', null=True, blank=True)

# First, get the user by their ID
user = User.objects.get(id=1)

# Access and print the user's phone number from their profile
print(user.profile.phone)

# Access and print the user's postcode from their profile
print(user.profile.postcode)

Attached is a real example using a Python shell to elucidate the scenario.

Upvotes: 0

neverwalkaloner
neverwalkaloner

Reputation: 47354

From the docs:

A DoesNotExist exception is raised when accessing the reverse relationship if an entry in the related table doesn’t exist.

So before accessing user's profile, you need to create this profile first:

u = User.objects.all()[0]
UserProfile.objects.create(user=u)

Upvotes: 1

Samuel Muiruri
Samuel Muiruri

Reputation: 522

Try it like this

from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.ForeignKey(User, related_name="profile")

Upvotes: 0

Related Questions