如何使用链接列表在django中查找下一个和上一个对象?

时间:2014-05-11 08:39:24

标签: python django django-models

假设Q&amp;网站。在结束点/q/<id2>打开问题时,它还应提供指向下一个/q/<id1>,之前问题/q/<id3>的链接。假设表格是pk值或时间戳的顺序。

这可以通过创建我现在正在使用的下面的方法来解决:

def next_q(self):
    # Ques model contain all questions
    # this method is a model method of Ques
    all_q = Ques.objects.all()
    q = None
    count = 1
    if count < all_q.count():
        try:
            q = all_q.get(pk=self.pk + count)
            break
        except ObjectDoesNotExist:
            count += 1
    return q

但是,我认为这种操作非常昂贵,只要请求问题Ques,它就会查询所有问题(/q/id个对象)。

我看到的一种可能的方法是使用链接列表的概念,其中下一个&amp;以前的对象id可以存储在当前对象中。

Ques模型中可能有两个字段

class Ques(models.Model):
    prev_q_id = models.IntegerField()
    next_q_id = models.IntegerField()

每当创建,编辑和删除新的Ques对象时,都会更新这些内容。这确保了我只查询一个对象。但是,我想知道这是否是一个好方法。如果不是我怎么办?

2 个答案:

答案 0 :(得分:2)

在订购结构上使用链接列表毫无意义,因为您的数据库已经为您提供了一个有序的记录列表,您可以根据需要订购数据,从而获得所需的任何项目。

这是一种可以为您提供所需内容的方法

class Ques(Model):
    ....

    @classmethod
    def get_next(cls, current_id):  # current_id is the id of current record
        try:
            return cls.objects.filter(id__gt=current_id).order_by("id")[0]
       except:
            return None

    @classmethod
    def get_previous(cls, current_id):
        try:
            return cls.objects.filter(id__lt=current_id).order_by("-id")[0]
        except:
            return None

使用classmethod在这里更有用,您只需获取下一个或上一个最接近的记录。如果没有记录,则获得None

答案 1 :(得分:0)

使用链接列表的方法是可行的,但您无需更改数据模型即可支持所需内容。相反,您可以简单地为所有大于主键的问题创建一个游标,然后阅读第一个。

请记住,objects.all()实际上并不读取所有对象。它只是为数据创建一个游标。您可以将光标视为数据库关于如何检索数据的“行动计划”。只有当您实际获取数据时,它才会开始读取数据库记录。

你想要的基本上是在sql中。

select * from Question where pk > question.pk order by pk

在django中,这就像是

all_q = Ques.objects.all()
all_q.filter(pk__gt=question.pk)
all_q.order_by('pk')  # not really necessary as this is done implicitly
next_q = all_q.first()

对于之前的记录,您也可以这样做,但使用相反的顺序或只是调用“last”而不是第一个。