Reputation: 93
{% if user.resume %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% endif %}
models.py
from django.db import models
from users.models import User
class Resume(models.Model):
name = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
@login_required()
def my_resumes(request):
return render(request, 'resumes/myresumes.html')
I'm trying to place an empty state if a user does not have a resume. Else, I want to show other information. I can't seem to get it to work. I think I am using the if
conditional statement wrong in the template.
Upvotes: 1
Views: 4369
Reputation: 141
You need to rename the backwards relationship on your resume class so you can access it using {{ user.resume }}.
By default the ForeignKey relationship you've defined from the resume to the user is accessible using user.resume_set. See the docs for more detail.
I'm guessing that you only want to have a single resume per user, so you'll probably want to use a OneToOneField instead of a ForeignKey.
class Resume(models.Model):
name = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="resume")
def __str__(self):
return self.name
Additionally, your if appears to be round the wrong way, given you probably want the form to appear when a resume doesn't exist.
{% if user.resume.exists %}
<p>More information here</p>
{% else %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}
Upvotes: 0
Reputation: 34922
First, your condition seems turned the wrong way. You code handling the case when the resume is not present is in the if user.resume
statement. So it should rather be if not user.resume
.
Second, the reverse relation is not named user.resume
but user.resume_set
. You can change this name using related_name
if you want. For instance: user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='resumes')
would enable to access it via user.resumes
instead of user.resume_set
.
Yet, if user.resume_set
will always be evaluated to if True
because it is a related manager, not a queryset. So you could do something like this:
{% if not user.resume_set.exists %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% endif %}
However, in your else
statement, you will likely iterate over resumes with something like this {% for resume in user.resume_set.all %}
. In such, case you will hit twice the database. Once for user.resume_set.exists
and once for user.resume_set.all
, which is not needed because you can know the result of user.resume_set.exists
from the result of user.resume_set.all
. Django templates allows you to do something like this to handle empty case when iterating an object:
{% for resume in user.resume_set.all %}
Your code to display a resume item here
{% empty %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}
But still, it is not very good practice to execute querysets in a template. To avoid this, you can pass it in your view:
@login_required()
def my_resumes(request):
context = {'resumes': request.user.resume_set.all()}
return render(request, 'resumes/myresumes.html', context)
Now you can do:
{% for resume in resumes %}
Your code to display a resume item here
{% empty %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}
Note that you can also use the previous syntax, it will only hit the database once:
{% if not resumes %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% for resume in resumes %}
Your code to display a resume item
{% endfor %}
{% endif %}
Upvotes: 3