count number of instances django template - django

I've read all the other answers posted with some saying you can and some saying you can't so I tried. What I'm trying to do is iterate my array and if the object's id matches, increment the counter and display it later. I have it set up like this:
{% with elect_count=1 %}
{% for device in devices %}
{% if device.ixDeviceType.ixDeviceClass_id == 3 %}
{{ elect_count|add:1 }}//increment the counter
{% endif %}
{% endfor %}
<li style="list-style: none;" class="padding5">
<span class="glyphicon glyphicon-flash" style="color: yellow; font-size: larger;"></span>
<span name="meter-count">{{ elect_count }}</span>//display total number of elect_count
<ul id="meter-summary">
</ul>
</li>
{% endwith %}
but when I run this, it displays 1 1 1 1 instead of incrementing this elect_count variable and when I do {{ elect_count }} it's 0

You cannot save the counter in template, but you could do it in views and pass it in context:
views.py
def view_function(request):
elect_count = 0
for device in devices:
if device.ixDeviceType.ixDeviceClass_id == 3:
elect_count += 1
context['elect_count'] = elect_count

Related

How to check active accordion based on object id?

Here {% c_url request 'display' %} this will return either display class or None. if display class return I want to keep accordion collapse open. But this is opening all the collapse.
I want to apply display class to the particular #collapseid only. How can I do it ?
template
{% for n in navs %}
<li>
<a
data-toggle="collapse"
class="sub{{n.id}} {% c_url request 'active' %}"
href="#collapse{{n.id}}"
aria-expanded="true"
aria-controls="collapse"
><p>
{{n.title}}
</p></a
>
<div class="collapse{{n.id}} {% c_url request 'display' %}" id="collapse{{n.id}}">
<ul class="nav">
{% for i in n.nav_set.all %}
..............
{% endfor %}
</ul>
</div>
</li>
{% endfor %}
c_url template tag
#register.simple_tag
def c_url(request, value):
if request.resolver_match.url_name in ['url1', 'url2']:
return value
I can suggest two 'easier' options to do it:
Set active status flag on n in navs in context (in views.py):
for n in navs:
if <condition for active>:
n.active = True
Then in the template:
{% if n.active %}display{% endif %}
Add an additional option to the context for the active collapse id:
views.py:
for n in navs:
if <condition for active>:
context['active_id'] = n.id
Then in the template:
{% if n.id == active_id %}display{% endif %}

Django template variable not set

The title says everything. Two days ago the following code worked fine but now journeys is not set or empty or ...
def map(request, jid):
journeys = None
if request.user.is_authenticated:
journeys = Journey.objects.filter(user_id=request.user.id)
#some stuff
context = {
'jc': len(journeys), #only for testing
'journeys': journeys
}
return render(request, 'JourneyMap/map.html', context)
map.html extends base.html
Inside base.html:
<div class="dropdown-menu" aria-labelledby="dropdown05">
<p>{{ jc }}</p> <-- only for testing
{% for journey in journeys %}
{% if journey.user_id == user.user_id %}
{% if forloop.counter < 4 %}
<a class="dropdown-item"
href="{% url 'JourneyMap_journey' jid=journey.id %}">{{ journey.title }}</a>
{% endif %}
{% endif %}
{% endfor %}
</div>
Result:
It seems like journeys length is 1, so the variable is actually set.
I think that your user check fails here.
{% if journey.user_id == user.user_id %}
What is user.user_id here? Is user another variable that lives somewhere outside of the given context? Then probably it's not set.
Otherwise, if you want to check for current user's id, perhaps you should do:
{% if journey.user_id == request.user.id %}

Django iteration (for ... in ...) how to put it in different divs?

I have few instances of model.
my model:
class Record(models.Model):
name = models.ForeignKey(Car)
image = models.ImageField(upload_to='images/')
created = models.DateTimeField(
default=timezone.now)
view:
def allrecords(request):
records = Record.objects.all().order_by('created')
return render(request, 'mycar/allrecords.html', {'records' : records})
I want show it on my website. In my template i have:
{% for record in records %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endfor %}
Now i get list of my records, but i would like put the newest record to first div, next to second etc. How can i do that?
I show simple screen how i would like have that (if someone will create new record, it will go to first div and other records will change place. Is any possibility to do something like that?
edit:
<div>
{% for record in records %}
{% if forloop.counter == 1 %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
{% endfor %}
</div>
<div>
{% for record in records %}
{% if forloop.counter == 2 %}
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
{% endfor %}
</div>
.
.
# till your 5th image
You can use forloop.counter to get the iteration number and check what is the iteration the loop and handle data accordingly.
In addition you can use CSS to make the layout work as you want.
Here is the information for Django template counter
Edit :
{% for record in records %}
<div>
{% if forloop.counter == 1 %}
# Here you can get your first images
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
</div>
<div>
{% if forloop.counter == 2 %}
# Here you can get your first images
<img src={{ record.image.url}}/>
<div>
{{record.name}}
</div>
{% endif %}
</div>
.
.
# till your 5th image
{% endfor %}
There are two ways to do this. If you want to set this option for a single view then:
def all_records(request):
records = Record.objects.all().order_by('-created')
return render(request, 'mycar/allrecords.html', {'records' : records})
You're almost correct but order_by('created') leads to asceding order while order_by('-created') leads to descending order which is what you require.
Alternatively, if you want to have this setting to apply to all views then set class Meta in your models.py which will ensure that wherever you use Record.objects.all() it returns Records in descending order of created field:
class Record(models.Model):
name = models.ForeignKey(Car)
image = models.ImageField(upload_to='images/')
created = models.DateTimeField(
default=timezone.now)
class Meta:
ordering = ('-created')
It's Django design pattern to make all logical decisions in models and views and only just plugin formatted data in templates. You shouldn't add any complex logic in templates.
I'm assuming the question means that the model might have more than 5 records. If so, a more generic solution would be
<div class='row'>
<div class='firstimage'>
<img src={{ records[0].image.url}}/>
{{record.name}}
</div>
{% for record in records %}
{% if forloop.counter > 1 %}
<div class='subsequentimage'>
<img src={{ record.image.url}}/>
{{record.name}}
</div>
{% endif %}
{% cycle "" "</div><div class='row'>" "" %}
{% endfor %}
</div>
Note the use of the 'cycle' tag to begin a new row div every third cell div.
I don't know what your CSS classes are to distinguish between rows and cells so I used 'row', 'firstimage' (which might be defined to take up twice as much width) and 'subsequentimage' as example classes.
I recommend you to use the context variables:
def all_records(request):
records = Record.objects.all().order_by('-created')
newest = records[:5]
oldest = records[5:]
return render(request, 'mycar/allrecords.html', {'newst' : newest,
'oldest': oldest })
In your template :
{% for new in newst %}
<div>what you want with news</div>
{% endfor %}
{% for old in oldest %}
<div>what you want with olds</div>
{% endfor %}

Django pagination - How to limit the pages?

I'm using this code to display the pagination on my page
<ul class="pagination pagination-sm">
{% if restaurants.has_previous %}
<li>Prev</li>
{% endif %}
{% for page in restaurants.paginator.page_range %}
<li class="{% if restaurants.number == page %}active{% endif %}">{{ page }}</li>
{% endfor %}
{% if restaurants.has_next %}
<li>Next</li>
{% endif %}
</ul>
The issue is that the code above shows all page like this:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | and so on..
Instead I would like to show something like this:
1 | 2 | 3 | 4 | 5
How can I do that?
This is my view:
def listing(request):
list_restaurants = ShopAccount.objects.filter(is_active=1)
# only active products
paginator = Paginator(list_restaurants, 20) # Show 20 products per page
page = request.GET.get('page')
try:
restaurants = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
restaurants = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
restaurants = paginator.page(paginator.num_pages)
return render_to_response('restaurants/list.html', {'restaurants': restaurants}, context_instance=RequestContext(request))
I use something like this :
<li {% ifequal page current %}class="active"{% endifequal %}>
<a href={% ifequal page -4 %}
"/blog/1/"><<
{% else %}{% ifequal page -3 %}
"/blog/{{ current | add:"-1" }}/"><
{% else %}{% ifequal page -2 %}
"/blog/{{ current | add:"1" }}/">>
{% else %}{% ifequal page -1 %}
"/blog/{{ maximum }}/">>>
{% else %}{% ifequal page 0 %}
"#">...
{% else %}{% ifequal page current %}
"#" class="page_link">{{ page }}
{% else %}
"/blog/{{ page }}/">{{ page }}
{% endifequal %}
{% endifequal %}
{% endifequal %}
{% endifequal %}
{% endifequal %}
{% endifequal %}
</a>
</li>
and these views :
def makepaginator(current, maximum):
"""makepaginator() returns a set of number which reprensents buttons.
-4 means first page.
-3 means previous page.
-2 means next page.
-1 means last page.
0 means a dot.
others means the number of the target page."""
NB_PAGES_LEFT_LEFT = 3
NB_PAGES_RIGHT_RIGHT = NB_PAGES_LEFT_LEFT
NB_PAGES_CENTER_RIGHT = 3
NB_PAGES_CENTER_LEFT = NB_PAGES_CENTER_RIGHT
i = 2
current = int(current)
if current > 1:
p = [-4, -3]
else:
p = []
p.append(1)
while i <= maximum:
if (i > NB_PAGES_LEFT_LEFT and i < maximum - NB_PAGES_RIGHT_RIGHT
and (i - current > NB_PAGES_CENTER_RIGHT
or current - i > NB_PAGES_CENTER_RIGHT + 1)):
p.append(0)
while (i > NB_PAGES_LEFT_LEFT
and i < maximum - NB_PAGES_RIGHT_RIGHT
and (i - current > NB_PAGES_CENTER_RIGHT
or current - i > NB_PAGES_CENTER_LEFT + 1)):
i += 1
else:
p.append(i)
i += 1
if current < maximum:
p.append(-2)
p.append(-1)
return (p)
def news(request, page_num=1):
paginator = Paginator(Article.objects.all().order_by('-date'), settings.ARTICLES_PER_PAGE)
try :
page = paginator.page(page_num)
print(type(page_num))
return (render(request, "main/blog.html",
{"paginator" : paginator, "page_num" : int(page_num),
"page" : page,
"buttons" : makepaginator(page_num,
paginator.num_pages)}))
except (PageNotAnInteger, EmptyPage) as e:
return (notfound(request))
With bootstrap I get this :
It may look dirty but it works with my website. You can try it.
If you have some improvements to suggests, I would be glad though. :)
ShopAccount.objects.filter(is_active=1)[:5]
Try this code above, or use the [:5] on the paginator.
I solved this issue with JS.
Here the views:
class AllOrders(LoginRequiredMixin, ListView):
model = Order
template_name = 'all_orders.html'
paginate_by = 20
def get_queryset(self):
filter_val = self.request.GET.get("filter", "")
order_by = self.request.GET.get("orderby", "id")
if filter_val != "":
orders = Order.objects.filter(Q(transaction_id__contains=filter_val) | Q(customer_id__auth_user_id__first_name__contains=filter_val) |
Q(customer_id__auth_user_id__last_name__contains=filter_val)).order_by(order_by)
else:
orders = Order.objects.all().order_by(order_by)
return orders
def get_context_data(self, **kwargs):
context = super(AllOrders, self).get_context_data(**kwargs)
context["filter"] = self.request.GET.get("filter", "")
context["orderby"] = self.request.GET.get("orderby", "id")
context["all_table_fields"] = Order._meta.get_fields()
return context
Here the template:
<nav class="d-inline-block">
<ul class="pagination mb-0">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.previous_page_number }}" tabindex="-1"><i class="fas fa-chevron-left"></i></a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1"><i class="fas fa-chevron-left"></i></a>
</li>
{% endif %}
{% for i in paginator.page_range %}
<li class="page-item {% if i == page_obj.number %}active{% endif %}"><a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ i }}">{{ i }} <span class="sr-only">(current)</span></a></li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="{% url 'custom_user:all_orders' %}?filter={{ filter }}&orderby={{ orderby }}&page={{ page_obj.next_page_number }}"><i class="fas fa-chevron-right"></i></a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#"><i class="fas fa-chevron-right"></i></a>
</li>
{% endif %}
</ul>
</nav>
Here the JS:
<script>
let pages = document.getElementsByClassName('page-item');
let pageActive;
if (pages.length > 5) {
for (let i = 0; i < pages.length; i++) {
if (pages[i].classList.contains('active')){
pageActive = i;
break;
}
}
for (let j = 0; j < pages.length; j++) {
if ( j != 0 && j != 1 && j < (pageActive - 1)) {
pages[j].setAttribute('hidden', true);
} else if (j != (pages.length - 1) && j != (pages.length - 2) && j > (pageActive + 1)) {
pages[j].setAttribute('hidden', true);
}
};
};
</script>
This is the result:
paginator

Get current URL kwargs in the template?

I'm accomplishing this at the moment by doing:
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
Which seems crazy counter intuitive to me.
Say if i was already at the urls of players/one/two/three
Is there an already prebuilt way to get current kwargs of one, two & three for use in templates?
Edit
urls.py
urlpatterns = patterns('',
url(
r'^$',
NationListView.as_view(),
name='index'
),
url(
r'^(?P<slug>[a-z-]*)/$',
NationDetailView.as_view(),
name='nation'
),
url(
r'^(?P<slug>[a-z-]*)/(?P<card_type>[a-z]*)/(?P<role_line>[a-z]*)/(?P<sort_by>[a-z0-9]*)/$',
NationDetailFilteredView.as_view(),
name='nation_filter'
),
)
The mixin that builds the context
class CoreDetailFilteredMixin(object):
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(CoreDetailFilteredMixin, self).get_context_data(**kwargs)
base_objects(context)
# Pull all the players that belong to the object_type
context['players'] = Player.objects.filter(
**{filters: context['object'].asset_id}
)
# Define the available card types
card_types = {
'if': {'card_type__gte': 2},
'gold': {'overall_rating__gte': 75},
'silver': {'overall_rating__range': (65, 74)},
'bronze': {'overall_rating__lte': 64}
}
# Check if the given card type is in the dictionary because 'all' throws an KeyError
if self.kwargs['card_type'] in card_types:
context['players'] = context['players'].filter(**card_types[self.kwargs['card_type']])
# Don't show inform cards for specific colour card types
if self.kwargs['card_type'] not in ['if', 'all']:
context['players'] = context['players'].exclude(card_type__gte=2)
# Define available role lines
role_lines = {
'att': 3,
'mid': 2,
'def': 1,
'gk': 0
}
# Check if the given role line is in the dictionary because 'all' throws an KeyError
if self.kwargs['role_line'] in role_lines:
context['players'] = context['players'].filter(role_line=role_lines[self.kwargs['role_line']])
# Define the available sort by keys
sorts = {
'ovr': 'overall_rating',
'att1': 'card_att1',
'att2': 'card_att2',
'att3': 'card_att3',
'att4': 'card_att4',
'att5': 'card_att5',
'att6': 'card_att6r'
}
# Add a descending order to the existing queryset
context['players'] = context['players'].order_by('-' + sorts[self.kwargs['sort_by']])
# Create pagination
cbv_pagination(self, context, context['players'], 28, 'players')
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
return context
How i use it currently in the template
{% with object.get_class_name|add:'s'|add:':'|add:object.get_class_name|add:'_filter'|lower as url_string %}
<dl class="sub-nav">
<dt>Card Type:</dt>
{% with 'all if gold silver bronze' as card_types %}
{% for ct in card_types.split %}
{% cycle 'All' 'Inform' 'Gold' 'Silver' 'Bronze' as card_type_name silent %}
{% if card_type == ct %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug ct role_line|default:'all' sort_by|default:'ovr' %}">
{{ card_type_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Role Line:</dt>
{% with 'all att mid def gk' as role_lines %}
{% for rl in role_lines.split %}
{% cycle 'All' 'Attackers' 'Midfielders' 'Defenders' 'Goalkeepers' as role_lines_name silent %}
{% if role_line == rl %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' rl sort_by|default:'ovr' %}">
{{ role_lines_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Sort By:</dt>
{% with 'ovr att1 att2 att3 att4 att5 att6' as sorts %}
{% for sort in sorts.split %}
{% ifequal role_line 'gk' %}
{% cycle 'Overall' 'Diving' 'Handling' 'Kicking' 'Reflexes' 'Speed' 'Positioning' as sorts_name silent %}
{% else %}
{% cycle 'Overall' 'Pace' 'Shooting' 'Passing' 'Dribbling' 'Defending' 'Heading' as sorts_name silent %}
{% endifequal %}
{% if sort_by == sort %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' role_line|default:'all' sort %}">
{{ sorts_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
{% endwith %}
As I learnt here, the view is already passed to the context (for class-based views). So you can do the following in the template without needing to explicitly pass the kwargs from the view:
{{ view.kwargs.card_type }}
{{ view.kwargs.role_line }}
{{ view.kwargs.sort_by }}
You can use dict.update():
update([other])
Update the dictionary with the key/value pairs from other, overwriting existing keys.
context.update(self.kwargs)