【问题标题】:How can you add a secondary ID for a model, based on its association with a particular object? [duplicate]如何根据模型与特定对象的关联为模型添加辅助 ID? [复制]
【发布时间】:2018-12-03 14:14:52
【问题描述】:

示例代码:

class Post(models.Model):
  ...

class Comment(models.Model):
  ...
  post = models.ForeignKey(Post, related_name='comments',
                  on_delete=models.CASCADE, null=False)
  post_comment_number = models.PositiveIntegerField(unique=True, null=False)

想象一个博客文章下面有一堆 cmets。我想为这些 cmets 中的每一个分配一个辅助 ID,表示评论和博客文章之间的关系 - 例如:评论 #1:...,评论 #2:...,等等。

我不想在前端执行此操作,因为例如,如果评论 #2 被删除,我不想再次为与此特定博客文章关联的另一个评论分配 #2 ID。

关于如何做到这一点的任何想法?非常感谢!

【问题讨论】:

  • Django 不允许在同一个模型中有多个AutoField(并且第一个已经被id 字段使用)。您可以创建一个单独的计数器表来跟踪post+comment_id 对并覆盖save() 方法以获取该帖子的下一个评论ID。不过,这可能会导致竞争条件,因此还要研究行锁定。
  • @Selcuk 能否请你给我看一个例子 - 或者给我指一个资源 - 用行锁定来做这个?
  • @Selcuk 非常感谢!我整天都在搜索,以为我在stackoverflow上看到了几乎所有与此相关的问题,但不知何故错过了那个问题。如果您愿意,请随时添加一些内容作为答案,以便我接受。
  • 如果您似乎在那里找到了答案,您可以将此问题标记为重复,以便将来的读者也可以参考其他问题。

标签: python sql django postgresql


【解决方案1】:

解决方法是删除帖子编号字段并添加时间戳字段或添加日期字段。通过使用此时间戳,您仍然可以按顺序获取特定帖子的所有 cmets。如果您仍想拥有 ID,您也可以维护一个自动递增 ID 字段。

class Post(models.Model):
...

class Comment(models.Model):
...
    id = models.AutoField(primary_key=True)
    post = models.ForeignKey(Post, related_name='comments',
                  on_delete=models.CASCADE, null=False)
    timestamp = models.DateTimeField(auto_now=True)

另一种解决方案是:

class Post(models.Model):
...

class Comment(models.Model):
...
    post = models.ForeignKey(Post, related_name='comments',
                  on_delete=models.CASCADE, null=False)
    post_comment_number = models.PositiveIntegerField(default=1) 

    def save(self, *args, **kwargs):
        obj = super(Comment, self).save(*args, **kwargs)
        try:
            last_comment = self.post.comment_set.all().orderby('-post_comment_number')[0]
        except KeyError:  # When there are no comments
            pass
        else:
            Comment.objects.filter(id=self.id).update(post_comment_number=last_comment.post_comment_number+1)
        return obj

但就像Selcuk 提到的那样,这可能会导致竞争条件。我更喜欢这个解决方案的解决方法。

【讨论】:

  • 由于竞争条件问题,我想避免第二种解决方案。至于第一个解决方案,即解决方法,我可以看到使用时间戳如何提供帮助,但这会留下一个主要问题。我可以使用时间戳在每条帖子下为每条评论指定一个数字——比如评论#1、#2、#3,基于它们的创建日期;但是,如果评论 #2 被删除,那么评论 #3 现在变成评论 #2。我想避免这种情况发生。我不希望将任何已删除评论的“编号”分配给另一条评论。关于如何做到这一点的任何想法?非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-26
  • 2023-03-25
  • 1970-01-01
相关资源
最近更新 更多