I have these two models and I want to display the project with a specific task in my page. These are my models:
class Project (models.Model):
name = models.CharField(verbose_name="Project name", max_length=25)
tasks = models.ManyToManyField(Task, verbose_name="tasksInProject", blank=True,
related_name="projects+")
class Task(models.Model):
name = models.CharField(verbose_name="Task", max_length=50)
I call this view:
class TaskToProjectFilterView(DetailView):
model = Task
template_name = "vivs/task_filter.html"
context_object_name = "task_filter"
And this is my html template:
<h4>filter : {{ task_filter }} </h4>
<h4>projects :
{% for element in task_filter.projects.all %}
{{ element }}
{% endfor %}
</h4>
This code displays the {{ task_filter }} but not the list of {{ task_filter.projects.all }}.
Can you help me? I don't understand my mistake. Thanks!
As schwobaseggl stated, remove the + sign and it should work as expected, using:
{% for element in task_filter.projects.all %}
From the Django Docs:
If you’d prefer Django not to create a backwards relation, set related_name to '+' or end it with '+'. For example, this will ensure that the User model won’t have a backwards relation to this model:
Related
hi i am new in django coding
i have 3 tables(models) in my different Django app , i try to make a simple report in htmpl page , so need to retrive specific data for each item base on foreign key.
by below code i can accress machine stored table in Html page by
making a loop , but i want to fetch data from other table and filter them ,
{% for m in machines %}
<h2>{{m.title}}</h2>
<h3>{{}}</h3>.
//i** need to access the ordertitle field in tb_order base on machine id. ??**
<p>{{ }}</p>.
// **access ordertitle in tb_order base on status field ??**
{%end for %}`
here is a view.py
def allmachinesLOGO(request):
machines=Machine.objects.all()
context ={'machines':machines}
return render(request,'pline/machineslogos.html',context)
Models :
class tb_order(models.Model):
ordertitle= models.CharField(max_length=200)
customer=models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL)
mould=models.ForeignKey(Mould, null=True, on_delete=models.SET_NULL, blank=True)
status=models.CharField(choices=status_choices, default="0", max_length=20)
accept=models.BooleanField
machine=models.ForeignKey(Machine,null=True, on_delete=models.SET_NULL, blank=True)
id =models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False, unique=True)`
class Machine(models.Model):
title = models.CharField(max_length=200)
machine_model = models.CharField(max_length=200, null=True, blank=True)
description = models.CharField(max_length=600, null=True, blank=True)
featured_image=models.ImageField(default="defaultmachine.webp", blank=True, null=True)
id=models.UUIDField(default=uuid.uuid4, unique=True,primary_key=True,editable=False)`
advice a solution
access ordertitle in tb_order base on status field ??
// i need to access the ordertitle field in tb_order base on machine id.
By using the primary model, you can get the data associated with it from the secondary model. To do this, a special property (object) with the name secondary model_set is created in the primary model by default. In your case, for example: tb_order_set(lower case). Using related_name for the ForeignKey (in which case it will be whatever you write it without the _set prefix).
In the template, the outer loop loops through the rows of the model: Machine. The internal one, through tb_order_set.all, accesses the rows of the tb_order model. Although in my opinion it is better to do all calculations and comparisons in views, and in templates only display information.
Template file:
{% for m in machines %}
<p>{{ m.tb_order_set.all }}</p>
{% for r in m.tb_order_set.all %}
<p>{{ 'ordertitle' }} : {{ r.ordertitle }} {{ 'status' }} : {{ r.status }}</p>
{% endfor %}
{% endfor %}
To show by specific status:
{% for m in machines %}
<p>{{ m.tb_order_set.all }}</p>
{% for r in m.tb_order_set.all %}
{% if r.status == '2' %}
<p>{{ 'ordertitle' }} : {{ r.ordertitle }} {{ 'status' }} : {{ r.status }}</p>
{% endif %}
{% endfor %}
{% endfor %}
no matter how many tutorials/documentation i read i still don't quite understand how exactly i'm supposed to be using prefetch_related.
My models.py:
class ProfileComment(models.Model):
author = models.ForeignKey('Profile', on_delete=models.CASCADE, null=True)
date_posted = models.DateTimeField(default=timezone.now, editable=False)
body = models.CharField(max_length=180, blank=True)
...
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
comments = models.ManyToManyField(ProfileComment, related_name='comments', blank=True)
avatar = models.FileField(upload_to=avatar_folder, default='user-avatar/default.png')
...
My views.py:
profile = Profile.objects.prefetch_related('comments').get(user=request.user)
And in template:
{% for comment in profile.comments.all %}
<div>
<p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
<p>Message: {{ comment.body }}</p>
<p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}
However, no matter what i put in prefetch_related, amount of queries just go up by like 5 for every record
.prefetch_related(…) [Django-doc] should be used to fetch related objects for a queryset in bulk. Since you write:
….get(user=request.user)
however it will not make any difference, since you only retrieve a single object, and it will thus prefetch the comments in an extra query.
What you can minimize however is the number of extra queries that originate from comment.author.user. This will make two extra queries per comment, since ForeignKeys are loaded lazily.
Your view can thus look like:
profile = Profile.objects.get(user=request.user)
comments = profile.comments.select_related('author', 'author__user')
where you pass both profile and comments to the template, and then retrieve it with:
{% for comment in comments %}
<div>
<p>Author: {{ comment.author.user }}</p><img src="{{ comment.author.avatar.url }}">
<p>Message: {{ comment.body }}</p>
<p>Date posted: {{ comment.date_posted }}</p>
</div>
{% endfor %}
here we thus read the comments from a queryset where we fetch the profile and the user of that profile in the same query. As a result we will make two queries: one for the Profile, and one for all the Comments including the .author and .author.user.
I want to get a count of all objects set that are False for the object field adult.
I am looping over the "Family" model in my template:
class Family(models.Model):
name = models.CharField(max_length=255)
class Person(models.Model):
family = models.ForeignKey(Family, on_delete=models.CASCADE, related_name='person', related_query_name='person')
adult = models.BooleanField()
Here is what I want to achieve in the template:
# views.py
families = Family.objects.all()
# index.html
{% for family in families %}
{{ family.name }} has {{ family.person(adult=False).count() }} non-adults!
{% endfor %}
If I understand you correctly I think your problem is best solved by using django annotatations (for details see the docs).
In your view annotate each Family object with the numer of adults:
families = Family.objects.annotate(non_adults=Count('person', filter=Q(person__adult=False)))
Then you can simply use this annotation in your template
{% for family in families %}
{{ family.name }} has {{ family.non_adults }} non-adults!
{% endfor %}
With annotations you can utilize the power of the database which is often more effective than querying and doing additional things in python.
I have created a OneToOneField(parent) in Child model with related_name='children'. In my views, I used select_related to get the queryset. But in my page the list of children associated to a parent shows empty.
Models.py:
class Parent(models.Model):
item = models.CharField(max_length=20)
class Child(models.Model):
parent = models.OneToOneField(Parent, unique = True, related_name = 'children')
price = models.IntegerField()
views.py:
def live_prices(request):
parent_queryset = Parent.objects.all().select_related('children')
return render(request, 'live_prices.html', 'parent_queryset' : parent_queryset)
Template:
{% for parent in parent_queryset %}
{% child in parent.children.all %}
{{ child.price }}
{% endfor %}
{% endfor %}
It's a one to one field, so you simply access parent.children (because you have related_name='children') instead of looping through parent.children.all().
Since there is only one child, I would remove the related_name='children', then you will access parent.child instead of parent.children. You don't need unique=True for a one-to-one field either.
parent = models.OneToOneField(Parent)
Then, in your template:
{% for parent in parent_queryset %}
{{ parent.child.price }}
{% endfor %}
Note that using select_related does not change the way you access the objects in the template, it just reduces the number of SQL queries.
I try to display a menu category ---> Subcategory ---> products.
I use a context_processor to display all the categories and submenus .
I need to get products based on category and subcategory
I can only display django.db.models.fields.related.ManyRelatedManager at object ....
class Categorias(models.Model):
nome_categoria = models.CharField(max_length=100)
class Subcategoria(models.Model):
nome_subcategoria = models.CharField(max_length=100)
class Product(models.Model):
categoria = models.ManyToManyField('Categorias')
subcategoria = models.ManyToManyField('Subcategoria')
context.py
def menu(request):
return {'menucategoria': Categorias.objects.all(),}
def submenu(request):
return {'submenu': Subcategoria.objects.all(),}
menu.html
{% for c in menucategoria %}
<ul>
<li class="block">
<input type="checkbox" name="item" id="{{c.id}}" />
<label for="{{c.id}}">{{c}}</label>
<ul class="options">
{% for p in produtos.subcategoria.all %}
<li>{{p}}</li>
{% endfor %}
</ul>
</li>
</ul>
{% endfor %}
{% for p in produtos.subcategoria.all %}
In Python you would get a TypeError: 'Manager' object is not iterable exception, but in templates if fails silently...
There are some more tweaks to be done... You seem to got it wrong with the related_name. Related name is used for reversing relationships, not following them. So probably this is what you're after:
class Categoria(models.Model): # singular!
nome_categoria = models.CharField(max_length=100)
class Subcategoria(models.Model):
nome_subcategoria = models.CharField(max_length=100)
class Product(models.Model):
# using ForeignKey instead of ManyToMany. Guessed so because "categoria" is singular, right?
categoria = models.ForeignKey('Categoria', related_name='produtos') # plural in related_name, and "products" not "category"
subcategoria = models.ForeignKey('Subcategoria', related_name='produtos') # plural in related_name, and "products" not "category"
Now you can do stuff like:
{% for p in categoria.produtos.all %}
somestuff...
{% for sc in p.subcategoria.all %}
somemorestuff...
P.S.
You can leave out the related_name altogether. A default related name will be used: product_set in this example.