Render relationship model in template - python

I am trying to render a model with a relationship but I am not able to do so.
class LogBook(models.Model):
name = models.CharField(max_length=50, verbose_name="Nom du registre de maintenance")
members = models.ManyToManyField(User)
class LogMessages(models.Model):
logbook = models.ForeignKey(LogBook)
message = models.CharField(max_length=200, verbose_name="Détail du problème")
class LogDone(models.Model):
logmessage = models.ForeignKey(LogMessages)
message = models.CharField(max_length=200)
My view:
log = get_object_or_404(LogBook, pk=log_id)
logmessages = LogMessages.objects.filter(logbook=log_id)
My template
{% for logmessage in logmessages.all %}
{{logmessage.logdone.message}}
{{% endfor %}}
But the logdone object is not showing, any idea ?

Since your LogMessage model has a foreign key to log done, it's not a One to One relation and you have to access the related LogDone objects using the _set notation. There's also a slight typo, I believe. It should logmessages and not logmessages.all
{% for logmessage in logmessages %}
{% for done in logmessage.logdone_set.all %}
{{ done.message }}
{% endfor %}
{% endfor %}

I forgot that I added a related_name equal to "logdones" so I did the following :
{% for logmessage in logmessages %}
{% for done in logmessage.logdones.all %}
{{ done.message }}
{% endfor %}
{% endfor %}
And now it is working, thanks to #Vishal

Related

How do properly make an if statement in html

Im supposed to write an if statement in a detail.html template that states "if project has tasks" display a table otherwise display "no tasks in project.
I've tried
{% if task in project %}
{% if task in projects_list %}
{% if tasks in project %}
"displays table"
{% else %}
<p>no tasks for this project</p>
{% endif %}
here is my task model
class Task(models.Model):
name = models.CharField(max_length=200)
start_date = models.DateTimeField()
due_date = models.DateTimeField()
is_completed = models.BooleanField(default=False)
project = models.ForeignKey(
"projects.Project",
related_name="tasks",
on_delete=models.CASCADE,
)
assignee = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
related_name="tasks",
on_delete=models.SET_NULL,
)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("show_my_tasks")
here is the view for projects
class ProjectListView(LoginRequiredMixin, ListView):
model = Project
template_name = "projects/list.html"
context_object_name = "projects_list"
If project is a list you probably want:
{% if project|length > 0 %}
Similar question Check if an array is not empty in Jinja2
If I'm understanding correctly, you want to check if a project has any relationship with a task. If this is so, you can refer to the project attribute on the Task model by using the related_name which is tasks in the template. For example:
# using project.tasks to check for an existing relationship with project and task;
# calling the count method as well to count how many tasks are connected to a project within the loop.
{% if project.tasks.count > 0 %}
# Displaying the table in here with the project's task info...
{% else %}
<p> no tasks for this project </p>
{% endif %}
Ideally, your for loop would look something like:
{% for project in projects_list %}
...
{% if project.tasks.count > 0 %}
# Displaying the table in here with the project's task info...
{% else %}
<p> no tasks for this project </p>
{% endif %}
...
{% endfor %}
That should work.
Partial answer, too long to add as a comment. You often don't need to handle the case of an empty list or set outside of the for loop. Instead:
{% for task in project.tasks %}
{% if forloop.first %}
<table> ... and table header
{% endif %}
<tr>
... stuff involving display of {{task.field}}s
</tr>
{% if forloop.last %}
</table> ... and any other table footer stuff
{% endif %}
{% empty %} ... optional
stuff to show if there are no tasks
{% endfor %}

How do I iterate ManyToMany field in Django template tag?

I have an object that contains a Many-to-Many field. I'm trying to iterate this field in Django template, but apparently I can't. Let me show you the code first.
models.py:
class Book(models.Model):
title = models.CharField(max_length = 100, blank=True)
category = models.ManyToManyField(Category)
def __str__(self):
return self.title
views.py:
def book_list(request):
books = Book.objects.all().order_by('-pk')
context = {
'books' : books,
}
return render(request, 'contents/book_list.html', context)
Template file:
{% for b in books %}
<div>
{{b.title}}
{% for cat in b.category %}
{{cat}}
{% endfor %}
</div>
{% endfor %}
Now I get 'ManyRelatedManager' object is not iterable error. How do I iterate the field and show all the category in each object?
It's because if you call b.category it returns only the relation object. To get its values (category objects) you have to add .all. Like this:
{% for b in books %}
<div>
{{ b.title }}
{% for cat in b.category.all %}
{{cat}}
{% endfor %}
</div>
{% endfor %}
By the way, I've also changed c.title to b.title, because I assume you want this book title, not something from global.

Showing a Django ForeignKey value in template

I'm trying to show a model's ForeignKey value in a template, all other fields are showing fine but I couldn't make it work. Here is my code:
models.py:
class BodyPart(models.Model):
body_part = models.CharField(max_length=20, unique = True)
class Exercise(models.Model):
body_part = models.ForeignKey(BodyPart, on_delete=models.CASCADE, default = "bodypart", related_name="bodypart")
views.py:
exercises = Exercise.objects.filter(category=exercisedetailcategory).values()
context = {
"exercises" : exercises,
}
return render(request,"exercises-categories.html",context)
template:
{% for exercise in exercises %}
<span class="post-meta-category">{{exercise.body_part}}</span>
<div class="post-item-description">
{{exercise.title}}
<p>{{exercise.content}}</p>
{% endfor %}
This is one of the many reasons why you should not use .values(). If you pass Exercise models, you can fetch the related object into memory. You can make use of .select_related(..) to optimize the query:
exercises = Exercise.objects.filter(
category=exercisedetailcategory
).select_related('body_part')
context = {
'exercises' : exercises,
}
return render(request, 'exercises-categories.html', context)
Then in the template, we can render this with:
{% for exercise in exercises %}
<span class="post-meta-category">{{ exercise.body_part.body_part }}</span>
<div class="post-item-description">
{{ exercise.title }}
<p>{{ exercise.content }}</p>
{% endfor %}
You can furthermore implement a __str__ method for BodyPart:
class BodyPart(models.Model):
body_part = models.CharField(max_length=20, unique=True)
def __str__(self):
return self.body_part
and then render this with:
{% for exercise in exercises %}
<span class="post-meta-category">{{ exercise.body_part }}</span>
<div class="post-item-description">
{{ exercise.title }}
<p>{{ exercise.content }}</p>
{% endfor %}
in your exercise model, ignore the default part.(its possible to show any message that tell users "no body_part" such as
{% if not exercise.body_part %} -> No thing to show)
and make sure, you have a value in your exercise.body_part Which it means you have to have an object in your BodyPart model in relation to the current object of this model.
also it should be {{ exercise.body_part.body_part }}
the second one is to extract the value of related BodyPart objects value

django entries of author

I need to get list of all authors and their publishes
{% for author in authors %}
{{ author.name }}
{% for publish in publishes %}
{{ publish.title }}
{% endfor %}
{% endfor %}
views.py:
def authors_list(request):
authors = Author.objects.all()
publishes = Group.objects.filter(author=author)
return render(request, 'app/authors_list.html', {'authors': authors,'publishes': publishes})
This way 'publishes' is not Defined.
Assuming you have a ForeignKey in Group model, You could do something like this,
{% for author in authors %}
{{ author.name }}
{% for publish in author.group_set.all() %}
{{ publish.title }}
{% endfor %}
{% endfor %}
You could access the groups of your authors with the related name.
For that, you can also define a related_name for your convenience.
You could add,
author = models.ForeignKey(Author, related_name='groups')
in your Group model.
If you have added the related_name, then you can call the related_objects like,
{% for publish in author.groups.all() %}
in your template.
Then change your views,
def authors_list(request):
authors = Author.objects.all()
return render(request, 'app/authors_list.html', {'authors': authors})
The problem is that publishes is not defined while you are trying to define publishes
It is misleading but the error is marked below:
publishes = Group.objects.filter(publishes=publishes)
^^^^^^^^^
I hope it will help you find the problem.
After your edit:
publishes = Group.objects.filter(author=author)
^^^^^^
I think you will need to define a #propery for Author:
Read this

Django: How to display author of query of posts?

I'm trying to make individual pages for each author showing their name and posts. I can't seem to get the username displayed.
views.py
class UserProfileView(generic.ListView):
template_name = 'howl/user-profile.html'
context_object_name = 'user_howls'
def get_queryset(self):
author = self.request.user
u = User.objects.get(username=author)
return Howl.objects.filter(author=u)
models.py
class Howl(models.Model):
author = models.ForeignKey(User, null=True)
content = models.CharField(max_length=150)
Here is where I'm stuck.
user-profile.html
{% extends 'howl/base.html' %}
{% block content %}
<h1>User: {{user_howl.author}}</h1>
{% for user_howl in user_howls %}
<ul>
<li>{{user_howl.content}}</li>
</ul>
{% endfor %}
{% endblock %}
The content is displayed just fine, but the heading just says "User: ", how do I give it a context without using a for loop?
I've tried:
{% for author in user_howls.author %}
<h1>User: {{author}}</h1>
{% endfor %}
and
{% if user_howls.author %}
<h1>User: {{user_howl.author}}</h1>
{% endif %}
Still the same outcome, displaying "User: "
user_howls is a queryset so it won't have an author attribute, you need to get the author of the iterated object
{% for howl in user_howls %}
<h1>User: {{ howl.author}}</h1>
{% endfor %}
More to the point though, it doesn't make sense to start from a Howl list, when you are just returning the results for the user_profile, nor does it make sense to use a ListView. so instead, start from the user and then look up its howls
user_obj.howl_set.all()
Since your queryset is based on the posts belonging to the current user, you can shortcut all of this and just show the user directly:
User: {{ user }}

Categories

Resources