Relational queryset not showing properly in template - django

I believe is a quite basic problem, but I'm trying to render in a template all the titles for an specific page, and inside that title its corresponding text. With these models:
class Page(models.Model):
page_title = models.CharField(_("title of the page"), max_length=50)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.page_title
class Category(models.Model):
category_name = models.CharField(_("name of the category"), max_length=50)
def __str__(self):
return self.category_name
class Title(models.Model):
title = models.CharField(_("titulo"), max_length=50)
page = models.ForeignKey(Page, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Text(models.Model):
title = models.ForeignKey(Title, verbose_name=_("titulo de la pagina a la que pertenece"), on_delete=models.CASCADE, default='')
content = models.TextField()
def __str__(self):
return f"{self.title}"
I am using this view to render the logic:
def index(request):
pages = Page.objects.all()
titles = Title.objects.filter(page__id=2)
for title in titles:
title_id = title.id
texts = Text.objects.filter(title__id=title_id)
context = {
'pages' : pages,
'titles' : titles,
'texts' : texts,
}
return render(request, 'index.html', context)
But with this approach the texts only gives me the text of the last title when rendered this way in template:
{% for page in pages %}
<h1>{{page}}</h1>
{% for title in titles %}
<h3>{{title}}</h3>
{% for text in texts %}
<p>{{text}}</p>
{% endfor %}
{% endfor %}
{% endfor %}
The desired rendering would be all the titles and texts were displayed like this:
Title 1
Text of title 1
Title 2
Text of title 2
Title 3
Text of title 3
For as many titles and texts there are in the database. What would be the approach for that?
Edit: the current output shows the titles correctly but the text is always the last one (in this case text 3)
Output

The problem is in the views logic:
try this:
def index(request):
pages = Page.objects.all()
titles = Title.objects.filter(page__id=2)
title_id = []
for title in titles:
title_id.append(title.id)
texts = Text.objects.filter(title__id__in=title_id)
context = {
'pages' : pages,
'texts' : texts,
}
return render(request, 'index.html', context)
Also in models.py change class Text as:
class Text(models.Model):
title = models.ForeignKey(Title, verbose_name="titulo de la pagina a la que pertenece", on_delete=models.CASCADE, default='')
content = models.TextField()
def __str__(self):
return self.content #here
Then in template do this:
{% for page in pages %}
<h1>{{page}}</h1>
{{texts}}
{% for text in texts %}
<h3>{{text.title}}</h3>
<p>{{text}}</p>
{% endfor %}
{% endfor %}
Hope this will work !

The answer was simple as I was iterating wrong in the template. I had to use _set.all in order to retrieve the correct child elements.
{% for page in pages %}
<h1>{{page}}</h1>
{% for title in titles %}
<h3>{{title}}</h3>
{% for text in title.text_set.all %} # This
<p>{{text.content}}</p>
{% endfor %}
{% endfor %}
{% endfor %}

Related

nothing is displayed on the page with all products in Django

There is a model with three classes of category-subcategory-products
class Category(models.Model):
name_category = models.CharField(verbose_name = 'name cat', max_length = 100, null=True)
image = models.ImageField(null=True, blank=True, upload_to="media/", verbose_name='pic')
slug = models.SlugField(max_length=160, unique=True, null=True)
def __str__(self):
return self.name_category
class Subcategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='категория', related_name='sub')
name_subcategory = models.CharField(verbose_name = 'name subcat', max_length = 100, null=True)
image = models.ImageField(null=True, blank=True, upload_to="media/", verbose_name='pic')
slug = models.SlugField(max_length=160, unique=True, null=True)
def __str__(self):
return self.name_subcategory
class Product(models.Model):
subcategory = models.ForeignKey(Subcategory, on_delete=models.CASCADE, verbose_name='категория',related_name='prod')
name_product = models.CharField(verbose_name = 'name product', max_length = 100, null=True)
image = models.ImageField(null=True, blank=True, upload_to="media/", verbose_name='pic')
price = models.IntegerField('price')
def __str__(self):
return self.name_product
views.py
class CategoryView(ListView):
"""all category"""
model = Category
class CategoryDetailView(DetailView):
"""all sub category"""
model = Category
class SubcategoryView(ListView):
"""all product"""
model = Subcategory
url.py
urlpatterns = [
path("", views.CategoryView.as_view()),
path('<slug:slug>/', views.CategoryDetailView.as_view(), name='category_detail'),
path('<slug:slug>/<slug:slug_sub>/', views.SubcategoryView.as_view(), name='subcategory_list'),
]
page template from which I go to the page with all products (category_detail.html)
{% extends 'base.html' %}
{% block content %}
<h2>{{ category.name_category }}</h2>
{% for sub in category.sub.all %}
{{sub.name_subcategory}}
<img src="{{sub.image.url}}" width="100px" height="100px">
{% endfor %}
{% endblock %}
page template (subcategory_list.html) with all products (here I did not write the output of the products because even the name of the subcategory is not transmitted)
{% extends 'base.html' %}
{% block content %}
{{sub.name_subcategory}}
{% endblock %}
I just can’t understand why it doesn’t display anything on the last page. Perhaps the problem is in the classes in views since previously tried to write only through functions
By default, on DetailView, Django sends an object to the context and therefore that's what you should access in your template. You can see it here
{% extends 'base.html' %}
{% block content %}
<h2>{{ object.name_category }}</h2>
{% for sub in object.sub.all %}
{{ sub.name_subcategory }}
<img src="{{ sub.image.url }}" width="100px" height="100px">
{% endfor %}
{% endblock %}
You also will need a SubCategoryDetailView if you want to see details of that. If you want to override how Django passes data to the context, you can declare context_object_name with whatever you like. Please also have a look here

django template not show ForeignKey items

I'm new to django I'm having a problem with my foreignkey items not displaying hope you can help me... thank you.
here's my models.py
class Reporter(models.Model):
name = models.CharField(max_length=20)
address = models.CharField(max_length=30)
def __str__(self):
return self.name
class News(models.Model):
headline = models.CharField(max_length=50)
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.headline
and my views.py
def index(request):
reportlist = Reporter.objects.all()
context = {
'reportlist': reportlist
}
return render(request, 'index.html', context)
and my template
{% block content %}
{% for r in reportlist %}
<p>{{r.name}}</p>
{% for items in r.item_set.all%}
<p>{{items.headline}}</p>
{%endfor%} <br/>
{%endfor%}
{% endblock %}
{% block content %}
{% for r in reportlist %}
<p>{{r.name}}</p>
{% for items in r.news_set.all%}
<p>{{items.headline}}</p>
{%endfor%} <br/>
{%endfor%}
{% endblock %}
your model name is News so you need model_name_set, i.e. news_set

My "detailed" view page isn't working. The web page content is invisible

EDIT: I fixed the views.py with Av4t4r's code but it still shows no content. When I type something in voodoo.html it actually shows content, but all of the content inside the {% block content %} are not showing. Why is that?
Hello I am trying to make a simply gallery app where the first view (listview) is a list of all the persons (which are the objects), and when a user clicks on one it proceeds to the next page with a given pk/id key. But when it comes to that page... the content is blank. Here is what I have:
urls.py:
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Images.objects.all(), template_name='imgboard/home.html')),
url(r'^imgboard/(?P<id>\d+)/$', views.voodoofunction, name='voodoofunction'),
]
views.py (I feel like this is where the problem is):
def voodoofunction(request, id=None):
instance = get_object_or_404(Moreimages, id=id)
context = { "object_list": instance, }
return render(request, "imgboard/voodoo.html", context)
models.py
class Images(models.Model):
name_person = models.CharField(max_length=70)
instagram = models.CharField(max_length=200)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return self.name_person
class Meta:
verbose_name_plural = 'Images'
class Moreimages(models.Model):
key = models.ForeignKey(Images, on_delete=models.CASCADE)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return str(self.key)
class Meta:
verbose_name_plural = "More Images"
listview_code.html
{% block content %}
{% for object in object_list %}
<p>{{object.name_person}}</p>
{% endfor %}
{% endblock %}
voodoo.html:
{% block content %}
<h2>{{ object.name_person}}<br></h2>
<h4>{{object.instagram}}</p></h4>
<br>
{% for object in object_list %}
<p><img src="{{object.img_url}}", width=350, height="360></img>"</p>
{% endfor %}
{% endblock %}
Your context has no "object" in it. And your "object_list" is an instance, not a list (so your for loop is doing nothing).

Get Featured Image from different Model

I have 2 model objects, Business & BusinessImage as so, listed with views and index.html. I am trying to list the business's featured image, but it's not happening. I am getting the following error:
'QuerySet' object has no attribute 'businessimage_set'
How can I get the business featured image for a list?
Business
class Business(models.Model):
name = models.CharField("Name", max_length=70, default="Business Name")
slug = models.SlugField()
description = models.TextField("About", max_length=400)
category = models.ManyToManyField(Category, verbose_name="Categories", blank=True)
order = models.IntegerField("Order", default=0)
claimed = models.BooleanField("Claimed", default=False)
featured = models.BooleanField("Featured", default=False)
class Meta:
ordering = ['order']
verbose_name = "Business"
verbose_name_plural = "Businesses"
def __str__(self):
return self.name
BusinessImage
class BusinessImage(models.Model):
business = models.ForeignKey(Business)
image = models.ImageField(upload_to="images/business")
title = models.CharField(max_length=120)
featured = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return self.title
view.py
from .models import Business, BusinessImage
def index_view(request):
latest_business_list = Business.objects.all()
images = latest_business_list.businessimage_set.all()
template = loader.get_template('index.html')
context = RequestContext(request, {
'latest_business_list': latest_business_list,
'images': images,
})
return HttpResponse(template.render(context))
index.html
{% block content %}
<div class="text-center business_title">
<h2>Featured</h2>
</div>
{% if latest_business_list %}
{% for business in latest_business_list|slice:":4" %}
{% if business.active %}
<div class="col-sm-6 col-md-3">
<li>{{ business.name }}</li>
{% for image in latest_business_list.businessimage_set.all %}
{% if image.featured %}
<a href="{% url 'single_product' product.slug %}">
<img src="{{MEDIA_URL}}{{image.image}}" alt="{{image}}">
</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
businessimage_set is an attribute of a Business instance, but you're trying to access it as an attribute of a queryset (i.e. list of businesses). If your goal is just to be able to access the images for each business in a template, you can leave out images entirely. Instead your template would have:
{% for image in business.businessimage_set.all %}
(Though look into prefetch_related for efficiency.)

How to correct wrong num_times in django-taggit-templatetags?

I have the following models
class Text(models.Model):
text = models.CharField(max_length=10000, blank=True)
tags = TaggableManager(blank=True)
author = models.ForeignKey(User)
date_created = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True) # changes on each edit
public = models.BooleanField(default=1)
def __unicode__(self):
return self.text
class Note(models.Model):
note = models.CharField(max_length=1000)
tags = TaggableManager(blank=True)
text = models.ManyToManyField(Text)
author = models.ForeignKey(User)
date_created = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True) # changes on each edit
public = models.BooleanField(default=1)
def __unicode__(self):
return u'%s' % (self.text.all())
I am using django-taggit and django-taggit-templatetags. When I make a view like this:
#staff_member_required #TODO disadvantage: redirects to admin page
def labels_all(request):
return render_to_response('labels_all.html', locals(), context_instance=RequestContext(request))
with a template like
{% extends 'base.html' %}
{% load taggit_extras %}
{% block content %}
{% get_taglist as all_labels for 'notes' %}
<div class="tag-cloud">
<ul>
{% for label in all_labels %}
<li>
<a href="/labels/{{ label.slug }}">
<font size={{label.weight|floatformat:0}}>
{{ label|capfirst }} ({{ label.num_times }})
</font>
</a>
</li>
{% endfor %}
</ul>
</div>
Both models have a TaggableManager. I get the wrong num_times value when I make a taglist for either of the two models. The num_times I get are the number of times a specific tags occurs across the two above models (for instance, 71). I only want the number of times the tag occurs in the Note model (50).
I think the problem is in line 48 of this code: https://github.com/feuervogel/django-taggit-templatetags/blob/master/taggit_templatetags/templatetags/taggit_extras.py
It uses a call to taggit_taggeditem_items. I do not know where this comes from. In the database I have: taggit-tag (colums: id, name, slug) and taggit_taggeditem (id, tag_id, object_id, content_type_id). I do not know where it gets the _items bit, but I think it is from taggit's models.py BaseClass.
Could the problem be in the unicode method (which uses text in both models)?
In short, I want a tagcloud or taglist for a specific model. How can I use taggit and taggit-templatetags (or an alternative) to calculate tag frequencies (num_times) per model?
Thanks.
Seems the name of your app is 'notes', and Text and Note are models inside this app.
If you want only tags used in model Text, you should use:
{% get_taglist as all_labels for 'notes.Text' %}
If you want only tags used in model Note, you should use:
{% get_taglist as all_labels for 'notes.Note' %}