15👍
Django’s database queries are evaluated lazily, so the result of thread.comment_set.all
is a QuerySet, not a list. A QuerySet supports many list-like functions, but not negative slicing, so the indexing error is not coming from the template filter itself. (If you’re curious, slices on QuerySet objects get translated into a limit
clause on the SQL statement, which is why you can’t use a negative number).
In general, Django encourages a strict decoupling of templates and models; the views.py
module is the glue where you do any work that requires knowledge of database models and queryset methods to translate your model data into simple variables and structures for the template.
Running a related query on a model from a template is not something you typically see in a Django template, and there’s a good reason for this. Right now, it may seem very simple to slice the last three elements from the comment_set. Keep in mind, though, that the database will not return results in any guaranteed order. This means that, in addition to your slice, you now also need to add an order_by clause; there’s simply no way to express this in a template, nor should there be. Better to think of the view as the translation between your model and the template, and let such database-facing work be done there, rather than embedded in HTML.
In this case, I would encourage you to pass an ordered slice to your template from the view:
# take first three sorted descending
comments = thread.comment_set.order_by('-something')[:3]
context = Context({'comments':comments})
return HttpResponse(tmplt.render(context))
If you must do the slicing in the template, and you really don’t care about sorting the results, pass a list to the template. The slice
filter will happily do negative slicing:
comments = list(thread.comment_set.all())
context = Context('comments':comments)
In the template:
{% for comment in comments|slice:"-3:" %}
14👍
I haven’t seen the dictsortreversed filter used too often, and according to the docs it takes a key to sort by
{% for comment in thread.comment_set.all|dictsortreversed:"name"|slice:"3" %}
- Next previous links from a query set / generic views
- Convert data on AlterField django migration
- How do I hide the field label for a HiddenInput widget in Django Admin?
- Django rest framework group based permissions for individual views
1👍
Use the “ordering” attribute of Meta class of the Comment class to set the required ordering of elements.
IMO templates is not the proper place to order your dataset. Ordering should be done in either Models or Views.
- Testing a custom Django template filter
- Cache busting in Django 1.8?
- Best practice when using folium on django
- Why does docker-compose build not reflect my django code changes?
- Can celery,celerybeat and django-celery-beat dynamically add/remove tasks in runtime without restart celerybeat?
1👍
I needed just this and made a more complete solution, I think. Hope people find it useful. The view needs to find the id of the last inserted record (example here). You have to reverse order and get the id (PK) of the newest last record entered which will now be the first record, easy to find now at the top of the heap ;-). Calculate the lower limit id value you desire, then sort from the lower to the newest or last entry using this operator at the end …[n:m] (I think that is just a list operator), dropping the unwanted records, and then present it in normal order. For a django tables example here is my code:
def showLatestRels(request):
#This view shows the latest 15 entries in the Release table
LastInserted = Release.objects.order_by('-pk')[0]
UpperLimit = LastInserted.id
LowerLimit = UpperLimit - 15
RelTable = Release.objects.all()
tablevalslat = ReleaseTable(RelTable[LowerLimit:UpperLimit])
RequestConfig(request).configure(tablevalslat)
return render(request, 'DCESrtap/latrels.html', {'tablevalslat': tablevalslat}
)
Lots of ways to do it, see Django docs Make/limit Queries
But couldn’t get the dictsort idea to work….
- How to create multiple workers in Python-RQ?
- Extending User object in Django: User model inheritance or use UserProfile?
- Extending generic view classes for common get_context_data
- Django collectstatic no such file or directory
- Auto Populate Slug field django
- Django Admin – add collapse to a fieldset, but have it start expanded
- How do I add custom actions to a change model form in Django Admin?
- Zip File downloaded from ReactJs/Axios is corrupted
- TemplateSyntaxError: 'with' expected with atleast one variable assignment
- Django / postgres setup for database creation, for running tests
0👍
You can reverse a queryset if it is already ordered by “created”. So here is a faster solution.
{% for comment in thread.comment_set.all.reverse|slice:":3" %}
Also if you don’t want in reversed order.
{% for comment in thread.comment_set.all.reverse|slice:":3"|dictsort:"created" %}
Although you should follow Jarrets Hardie advice above and do all that logic in the views, rather then in the templates.
- Django, how to get a user by id, using the django.contrib.auth.models.User
- Is uwsgi protocol faster than http protocol?
- How to setup APScheduler in a Django project?
- Django – check cookies's "SameSite" attribute
- A good way to encrypt database fields?