I have these models in my models.py
User Model
class User(AbstractBaseUser, PermissionsMixin):
"""Custom user model"""
email = models.EmailField(max_length=255, unique=True)
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
def __str__(self):
return '{}'.format(self.email)
UserInfo Model
class UserInfo(models.Model):
"""User's Info"""
user = models.OneToOneField(User, related_name="parent_user", on_delete=models.CASCADE)
image = models.ImageField(upload_to=user_image_file_path)
age = models.IntegerField()
bio = models.CharField(max_length=400)
def __str__(self):
return '{}'.format(self.user)
My-template
In my template i am passing some filtered User Profiles
(let's say filtering by age, if age > 25
) now i need to show the name of the user(first_name
) as well but i don't know how to call a OneToOnefield reversely. Help is really appreciated :).
{% for p in profiles %}
<div class="profile-container" style="position: relative">
<div class ="left-div">
<div class="mySlides fade">
<img src="media/{{p.image}}" style="width:100%" id="user-media-img">
<div class="text">
User First Name is : {{`What to type here?`}}
</div>
</div>
</div>
<div class="right-div">
<div class="details">
<h1>BIO</h1>
<p>{{p.bio}}</p>
<h1>Age:</h1>
<p>{{p.age}}</p>
</div>
</div>
</div>
{% endfor %}
EDIT :
My views.py
:
I am passing a list named profiles which have filtered profiles based on 2-3 different type of filters so the code will be too much to paste here with all the references,
I am pasting short version here:
start =18
end=25
matching = UserInfo.objects.filter(
age__gte=start, age__lte=end
).values()
for z in matching:
if z['user_id'] not in rec_ids:
profiles.append(z)
print('profiles====', profiles)
context = {
'profiles' : profiles,
}
return render(request, 'home/news.html', context)
Pasting the output here
profiles==== [{'id': 18, 'user_id': 8, 'image': 'uploads/user/image/9d096190-73a0-4885-b4cd-ef6c7229b9eb.png', 'age': 23, 'bio': 'cool'}..etc]
Thanks :)
As @khadim hussen wrote in the comment you should use the following syntax:
p.user.first_name
Where p
is your UserInfo
model and p.user
is the reference to the OneToOne realationship.
Note that when you don't have a related user with p -> user the value you will return is None
.
If you want to show different info than None
in your template just can do the following:
{{p.user or 'Without User'}}
But in your views yo will get a RelatedObjectDoesNotExists
to ensure in your views that the relationship exists you can make the following validation:
p = UserInfo.objects.first()
if hasattr(p, 'user'):
user = p.user
Other thing that is important is when you have a related_name property as in your example:
user = models.OneToOneField(User, related_name="parent_user", on_delete=models.CASCADE)
So in this case you need to refer to the user
property with the related_name
.
In a more concrete way you have to do as following:
{{ p.parent_user.first_name }}
One important thing is that if you ar using queryset.filter(...).values()
so if you want to load values from other model you can use the following:
queryset.filter(...).values('image','age','bio','user','parent_user__first_name',...)
``
And in your template:
```python
{% p.parent_user__first_name %}
That's it.