So i'm trying to filter my model in this way in views.py:
news_list = list(models.Entry.objects.filter(category='news'))
and the problem is that the list cant be accessable from the django templates.
this is the way I'm trying to access it in home.html:
{% for news in news_list %}
{{ news.title }}
{% endfor %}
and this:
{{ news_list.0.title }}
I'm sure the way that I created the list is right beauce when I loop through the list in the views.py it show up in the terminal.
I'm using python3.3 and django 1.8.3
views.py :
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django.views import generic
from . import models
from blog.models import Entry
class BlogIndex(generic.ListView):
queryset = models.Entry.objects.published()
template_name = "home.html"
paginate_by = 3
news_list = Entry.objects.filter(category='news')
i = 0
for x in news_list:
i = i+1
print(x.title,i)
You are trying to access news_list in the template when it is infact not present in the template.
You need to pass news_list in the context data. Override the get_context_data() and pass this variable.
class BlogIndex(generic.ListView):
queryset = models.Entry.objects.published()
template_name = "home.html"
paginate_by = 3
def get_context_data(self, **kwargs):
context = super(BlogIndex, self).get_context_data(**kwargs)
context['news_list'] = Entry.objects.filter(category='news') # pass 'news_list' in the context
return context
Then in your template, you can use the normal for loop.
{% for news in news_list %}
{{ news.title }}
{% endfor %}
Note: You don't need to convert the QuerySet to a list as it is already an iterable.
The queryset result can be used to iterate in django template. So there is no need to convert query set object into list. List is not iterable in django template though python does. You can use django-mptt is a premade solution, which should fit your problem quite good.
That's because in django you don't access lists, but querysets. Try:
context['news_list'] = Entry.objects.filter(category='news')
Related
My model object have a IntegerField but I want to be able to render it differently on my html page, like lets say the object IntegerField is 500000 I want to render it as 500 000$ on my html page. So Add a space before the last 3 number and add a $ at the end.
I have a models with a IntegerField that look like this
class Listing(models.Model):
listing_price = models.IntegerField(max_length=100)
In my view I extract the models like this
def home(request):
listing_object = Listing.objects.all()
context = {
"listing_object": listing_object,
}
return render(request, "main/index.html", context)
I render the data like this
{% for listing in listing_new_object %}
{{listing.listing_price}}
{% endfor %}
You have two options:
Manipulate the context to make a list of tuples:
context = {
"listing_object": [(listing, f'{listing.listing_price:,}'.replace(",", " ")) for listing in listing_object]
}
then in your template:
{% for _, price in listing_new_object %}
{{price}}
{% endfor %}
The other option is to make a Django template filter
{{ listing.listing_price|price_format }}
from django import template
register = template.Library()
def price_format(value):
return f'{value:,}'.replace(",", " ")
register.filter(price_format)
I am trying to render two differents models using a loop in my templates/dashboard/home.html using Class Based View.
Let's have a look on my code :
views.py
class DashboardListView(ListView):
model = Links
template_name = 'dashboard/home.html'
class ContentListView(ListView):
model = Dashboard
template_name = 'dashboard/home.html'
First I would like to used the same ListView but was unable to do so.
My home.html
{% for dashboard in object_list %} {{dashboard.content}} {% endfor %}
{% for links in object_list %} {{links.content}} {% endfor %}
I would like to render those two models but I can only render one and the other object list will take the content for the preivous one.
Thanks for your help
First you can specify a different Mae for the list of your objects using:
context_object_name =‘links_list’
Then you can add different elements to the context extending this method:
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet
context[‘dashboard_list’]= Dashboard.objects.all()
return context
I have a template_tag.py:
from django import template
from myapp.views import RenderView
register = template.Library()
#register.inclusion_tag("template_tag.html")
def render_myapp():
rv=RenderView()
return rv.get_context_data()
and myapp.views.py:
from django.views.generic.base import TemplateView
class RenderView(TemplateView):
template_name = "test.html"
def get_context_data(self, **kwargs):
context = super(RenderView, self).get_context_data(**kwargs)
context["test"] = 1 # this is hit twice in the debugger
return context
template_tag.html:
{% if test %}
{{ test|safe }}
{% endif %}
base.html (different app):
{% load template_tag %}
{% render_myapp %}
I wonder why RenderView().get_context_data() is hit twice in the debugger? I don't call it twice in my template. It's probably because TemplateView already calls get_context_data and then I call it again rv.get_context_data(). But then how should my template_tag.py look like to not call get_context_data() again?
There seem to be two situations here.
In one case, the template tag is always in a template that is rendered by your RenderView. In which case, there doesn't seem to be any need for a tag; you should just either include template_tag.html or put its code directly into test.html.
In the other case, the tag is in another template, or in a range of templates that may or may not be rendered by RenderView. In which case, why is the context data for that page defined in RenderView? It should be defined directly in render_myapp().
from django.views import generic
from .models import Inspectionfile
from .models import posts
class IndexView(generic.ListView):
template_name = "posts/index.html"
def get_queryset(self):
return Inspectionfile.objects.all()
class DetailView(generic.DetailView):
model = Inspectionfile
template_name = "posts/detail.html "
#index template
<ul>
{% for o in object_list %}
<li>{{o.document_title}} </li>
{% endfor %}
</ul>
#detail template
<h1>{{ o.document_title }}</h1>
My Index template works but the detail template does not seem to take the value so just appears blank . So is the 'o' not being passed to detail ?? I have not been able to solve this. BTW document_title is one of the field of my inspectionfile model. I checked my url regex and it seems to work fine.
o is an object which only exists within the for loop in your list view template. It isn't passed anywhere.
The detail view has its own context; there the object that is identifued by the url argument is called just object.
I have created a template tag and trying to loop through the results from the template tag
but I don't get any results
tags.py
from django import template
from loadprograms import dbcontext
register = template.Library()
#register.simple_tag
def get_category():
x = dbcontext.DBContext()
results = x.executequery("Select name from Categories")
categories = [each[0] for each in results]
return categories
template code
{% load category_tags %}
{% get_category %}
{% for each in get_category %}
{{ each }}
{% endfor %}
The {% get_category %} prints all the categories without any issues but the for loop stmt
that loop through the results does not work
What could be the problem?
To make this change in your tag, you'll have to set a variable in the context, but if your objective is to have a list of categories available in templates, just like you would have passed it in from the view - then you need to write a template context processor, which will allow all views to have this variable in their context.
A template context processor is just a method that adds to the request context, by returning a dictionary. Think of it like a view function, that just returns a context.
from .models import Categories
def cat_names(request):
return {'category_names': Category.objects.values_list('name', flat=True)}
To activate this context processor, you have to do a few things:
Add the above code to a file called template_processors.py in the same place as your models.py and views.py.
In your settings.py, add the fully-qualified name of the method to the TEMPLATE_CONTEXT_PROCESSORS setting, making sure you don't override the defaults. To do this easily, import the default settings first, then add to it:
from django.conf.default_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
TEMPLATE_CONTEXT_PROCESSORS = TCP + ('yourapp.template_processors.cat_names',)
Use the render shortcut, which will make sure the context is correctly passed.
In your views, you can now just do this:
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
In your home.html, you can now do:
{% for name in category_names %}
{{ name }}
{% endfor %}