在Django中我有Letter
模型:
class Letter(models.Model):
letter_date = models.DateField(blank=False, null=False)
使用DateDetailView()
查看单个字母时,我想显示" next"和"之前"链接。要获得下一个/上一个Letter
我可以在其中一个视图方法中执行此操作(类似于获取next_letter
):
try:
previous_letter = self.model.objects.filter(
letter_date__lt=date).order_by('-letter_date')[:1].get()
except self.model.DoesNotExist:
previous_letter = None
如果每天只有一个Letter
,但是有些日子有多个字母,这个代码会在同一天跳过后续字母,这样可以正常工作。
如何确保下一个/上一个不会跳过字母?这听起来并不难,但我的大脑正在挣扎......
编辑:如果它有帮助,可以列出部分Letter
个日期及其pk
的日期:
答案 0 :(得分:1)
您需要向order_by
添加第二个参数。同时还为filter
方法添加了第二个参数。这样,Django将返回日期小于date
的对象列表,并先按letter_date
字段排序,然后按primary key
排序。
previous_letter = self.model.objects.filter(
letter_date__lt=date, pk__gt=pk).order_by('-letter_date', 'pk')
答案 1 :(得分:1)
尝试了几件事后......
我认为唯一/最好的方法是将另一个字段添加到Letter
,在订购时用作辅助字段,以便同一天的字母始终采用相同的顺序:
class Letter(models.Model):
letter_date = models.DateField(blank=False, null=False)
order = models.PositiveSmallIntegerField(blank=False, null=False, default=0)
class Meta:
ordering = ['letter_date', 'order',]
然后在视图中,我们必须从同一天或 a Letter
查找较早的Letter
。这是我的完整视图,以防它对任何人都有用:
from django.db.models import Q
from django.views.generic.dates import DateDetailView
from letters.models import Letter
class LetterDetailView(DateDetailView):
model = Letter
date_field = 'letter_date'
year_format = '%Y'
month_format = '%m'
day_format = '%d'
def get_context_data(self, **kwargs):
context = super(LetterDetailView, self).get_context_data(**kwargs)
extra_context = self.get_next_previous()
context.update(extra_context)
return context
def get_next_previous(self):
date = self.model.letter_date
order = self.model.order
try:
previous_letter = self.model.objects \
.filter( \
Q(letter_date__lte=date, order__lt=order) \
| \
Q(letter_date__lt=date) \
) \
.order_by('-letter_date', '-order')[:1] \
.get()
except self.model.DoesNotExist:
previous_letter = None
try:
next_letter = self.model.objects \
.filter( \
Q(letter_date__gte=date, order__gt=order) \
| \
Q(letter_date__gt=date) \
) \
.order_by('letter_date', 'order')[:1] \
.get()
except self.model.DoesNotExist:
next_letter = None
return {
'previous_letter': previous_letter,
'next_letter': next_letter,
}
我不想添加其他字段,但我认为这是保持列表和下一个/上一个链接一致的唯一方法。