对相关(通过外键)对象强制执行订单

时间:2009-12-19 19:49:40

标签: sql django language-agnostic

好的,想象一下典型的场景, - 附有一个线程对象和注释。它可以用django ORM的术语表达,大致如下:

class Thread(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=255)

class Comment(models.Model):
    id = models.AutoField(primary_key=True)
    content = models.TextField()
    created = models.DateTimeField(editable=False)
    thread = models.ForeignKey(Thread, related_name='comments')

    def save(self, force_insert=False, force_update=False):
        self.created = datetime.datetime.now()
        super(Comment, self).save(force_insert, force_delete)

因此,在显示实际数据时,评论将按其创建时间排序(因为我喜欢进行假设,身份字段也保证正确的顺序记录)。

但是如果我需要能够控制(和改变)注释必须出现在线程中的顺序才能将注释从一个线程移动到另一个线程。

这可以通过在评论模型中添加“序列”字段并限制评论模型的“序列”字段和“线程”字段组合的唯一性来实现(这样就可以在具有相同序列号的线程中没有注释)。这些字段上的唯一键应该就足够了(就django而言,我认为可以通过unique_together完成。)

但是,这会增加计算(和编码:P)开销,因为如果要更改注释的顺序,通过更改其序列号,还必须使用比目标更高的序列号更新注释。评论的序列号。等等。这只是在寻找麻烦。

不知何故,我无法理解这一点。也许我只是错过了什么?

(如果有可能的话,不要将此视为仅限django的问题.IMO它是语言无关的,因为它没有任何关于它的django特定的,当你想到它时)

编辑:我突然意识到,问题中没有实际问题。所以问题是,除了我所描述的显而易见的方式之外,实现这种模型的最轻量化方法是什么(对我来说似乎太麻烦)。

3 个答案:

答案 0 :(得分:2)

如果为Comment类指定ordering属性,则在显示注释的任何位置都将遵循该顺序。

class Comment(models.Model):
    id = models.AutoField(primary_key=True)
    content = models.TextField()
    created = models.DateTimeField(editable=False)
    thread = models.ForeignKey(Thread, related_name='comments')

    class Meta:
        ordering = ('-created')

    def save(self, force_insert=False, force_update=False):
        self.created = datetime.datetime.now()
        super(Comment, self).save(force_insert, force_delete)

The docs are here

如果您将注释从线程A移动到线程B,由于指定的顺序,它仍将以正确的创建顺序显示...

但也许我误解了你的问题......


编辑:好的,所以你的问题归结为:

  

“但是,如果我需要能够控制(和改变)注释必须在线程中出现的顺序,并且能够将注释从一个线程移动到另一个线程,那该怎么办呢。”

我认为你不会找到除你提到的机制之外的其他机制:评论类的序数。

并且,是的,当您将注释从线程移动到线程时,您必须有一些逻辑来在必要时重新排序。

如果这确实是你的要求,我认为没有任何机制让你的生活更轻松 - 抱歉。

答案 1 :(得分:1)

如果我理解你的问题(我不完全确定),你想创建和维护一个相对于一个线程的任意注释顺序。

我知道这样做的唯一方法是在Comment中有一个排序字段,或者在Thread中有一个Comment-of-Comment-in-order字段,或者可能是一个单独的表有一个(Thread) -id,Comment-id,order)元组。

对于我2年前做过的网站,我们选择了一个包含10-30篇文章的中间选项。我在时事通讯的管理页面上使用了一些jQuery魔法,它让管理员随机播放文章标题,而在后台它不断更新时事通讯的Article-ids-in-order字段。

答案 2 :(得分:0)

另一种方法是使用浮点数作为排序字段。这样,如果您想在线程的中间放置注释,您只需计算上一个注释和下一个注释的平均值,并将其用于您要插入的注释的排序字段。当然,在开始获得相同的值之前,您可以对浮点进行除法的次数有限,但通过将所有订单字段定期乘以2即可轻松解决。