59๐
Add an order_by
clause to ensure it orders by number
.
next_issue = Issue.objects.filter(title=title, number__gt=issue.number).order_by('number').first()
36๐
I know this is a bit late, but for anyone else, django does have a nicer way to do this, see https://docs.djangoproject.com/en/1.7/ref/models/instances/#django.db.models.Model.get_previous_by_FOO
So the answer here would be something something like
next_issue = Issue.get_next_by_number(issue, title=title)
Django managers to do that with a bit of meta class cleaverness.
- [Django]-Django Cache cache.set Not storing data
- [Django]-Get Model instance from Form without saving
- [Django]-How do I reuse HTML snippets in a django view
8๐
If itโs required to find next and previous objects ordered by field values that can be equal and those fields are not of Date*
type, the query gets slightly complex, because:
- ordering on objects with same values limiting by
[:1]
will always produce same result for several objects; - object can itself be included in resulting set.
Hereโs are querysets that also take into account the primary keys to produce a correct result (assuming that number
parameter from OP is not unique and omitting the title
parameter as itโs irrelevant for the example):
Previous:
prev_issue = (Issue.objects
.filter(number__lte=issue.number, id__lt=instance.id)
.exclude(id=issue.id)
.order_by('-number', '-id')
.first())
Next:
next_issue = (Issue.objects
.filter(number__gte=issue.number, id__gt=instance.id)
.exclude(id=issue.id)
.order_by('number', 'id')
.first())
- [Django]-Django Rest Framework POST Update if existing or create
- [Django]-Django: How to manage development and production settings?
- [Django]-Django type object Http404 has no attribute get
0๐
from functools import partial, reduce
from django.db import models
def next_or_prev_instance(instance, qs=None, prev=False, loop=False):
if not qs:
qs = instance.__class__.objects.all()
if prev:
qs = qs.reverse()
lookup = 'lt'
else:
lookup = 'gt'
q_list = []
prev_fields = []
if qs.query.extra_order_by:
ordering = qs.query.extra_order_by
elif qs.query.order_by:
ordering = qs.query.order_by
elif qs.query.get_meta().ordering:
ordering = qs.query.get_meta().ordering
else:
ordering = []
ordering = list(ordering)
if 'pk' not in ordering and '-pk' not in ordering:
ordering.append('pk')
qs = qs.order_by(*ordering)
for field in ordering:
if field[0] == '-':
this_lookup = (lookup == 'gt' and 'lt' or 'gt')
field = field[1:]
else:
this_lookup = lookup
q_kwargs = dict([(f, get_model_attr(instance, f))
for f in prev_fields])
key = "%s__%s" % (field, this_lookup)
q_kwargs[key] = get_model_attr(instance, field)
q_list.append(models.Q(**q_kwargs))
prev_fields.append(field)
try:
return qs.filter(reduce(models.Q.__or__, q_list))[0]
except IndexError:
length = qs.count()
if loop and length > 1:
return qs[0]
return None
next_instance = partial(next_or_prev_instance, prev=False)
prev_instance = partial(next_or_prev_instance, prev=True)
- [Django]-Django migration with uuid field generates duplicated values
- [Django]-Django download a file
- [Django]-Make sure only one worker launches the apscheduler event in a pyramid web app running multiple workers
0๐
note that do not use
object.get(pk=object.pk + 1)
these sorts of things, IntegrityError occurs if object at that pk is deleted, hence always use a query set
for visitors:
''' Useage '''
"""
# Declare our item
store = Store.objects.get(pk=pk)
# Define our models
stores = Store.objects.all()
# Ask for the next item
new_store = get_next_or_prev(stores, store, 'next')
# If there is a next item
if new_store:
# Replace our item with the next one
store = new_store
"""
''' Function '''
def get_next_or_prev(models, item, direction):
'''
Returns the next or previous item of
a query-set for 'item'.
'models' is a query-set containing all
items of which 'item' is a part of.
direction is 'next' or 'prev'
'''
getit = False
if direction == 'prev':
models = models.reverse()
for m in models:
if getit:
return m
if item == m:
getit = True
if getit:
# This would happen when the last
# item made getit True
return models[0]
return False
Usage
# you MUST call order by to pass in an order, otherwise QuerySet.reverse will not work
qs = Model.objects.all().order_by('pk')
q = qs[0]
prev = get_next_or_prev(qs, q, 'prev')
next = get_next_or_prev(qs, q, 'next')
- [Django]-Django: templatedoesnotexist gis/admin/openlayers.html
- [Django]-Select distinct values from a table field
- [Django]-Why does Django make migrations for help_text and verbose_name changes?
0๐
It works for me
next_post = Blog.objects.filter(date__lte=self.object.date, published=True).exclude(id=self.object.id).order_by('-date').first()
next_post = next_post if next_post else Blog.objects.filter(published=True).first()
previous_post = Blog.objects.filter(date__gte=self.object.date, published=True).exclude(id=self.object.id).order_by('date').first()
previous_post = previous_post if previous_post else Blog.objects.filter(published=True).last()
- [Django]-Django request to find previous referrer
- [Django]-What is a Django "app" supposed to mean?
- [Django]-How can I temporarily disable a foreign key constraint in MySQL?
-3๐
next_obj_id = int(current_obj_id) + 1
next_obj = Model.objects.filter(id=next_obj_id).first()
prev_obj_id= int(current_obj_id) โ 1
prev_obj = Model.objects.filter(id=prev_obj_id).first()
#You have nothing to loose hereโฆ This works for me
- [Django]-How to see which tests were run during Django's manage.py test command
- [Django]-Django 1.4 โ can't compare offset-naive and offset-aware datetimes
- [Django]-How to return custom JSON in Django REST Framework