为模型生成唯一标识符

时间:2011-02-10 22:14:14

标签: django unique

我有一个包含FileField的Model。 我希望这个FileField有一个独特的路径。

首先,关于使用条目的ID,但是Django将文件移动到它的upload_to路径,然后保存条目,因此ID为空。

此外,我不能使用类似标题或模型的任何其他元素(创建日期除外),因为它们可以由用户更改。每次用户更改其条目的标题时,我都不希望复制/删除文件(如果我将标题用作路径的一部分)。

在这里开始我的研究,我发现了这些:

  • 生成唯一键并将其与数据库进行比较。虽然密钥存在,但我们生成一个新密钥(Django, unique field generation):问题是在拥有唯一密钥之前可以对数据库执行的潜力是什么

  • 从创建日期获取时间戳。这里的问题是,如果两个人在同一时间添加文件,则会产生冲突

我希望这个唯一ID尽可能小,最大长度为7会很棒。完美的解决方案是拥有条目的ID。你知道一个解决方法吗(在移动文件到 upload_to 文件夹之前调用save()?)如果没有,哪个实现最好,基于一个我的解决方案或你认为更好的解决方案?

2 个答案:

答案 0 :(得分:1)

由于默认情况下FileField为null = True,blank = True,因此可能会将模型保存两次,首先删除文件值(= None),保存,然后添加文件值(先前存储在临时var中的,然后再次保存。

这是代码

# this method goes in your model
def save(self, *args, **kwargs):
    # ignoring the double save if this is an update or if there is no files
    if self.pk or not self.file:
        return super(MyModel, self).save(*args, **kwargs)

    old_file = self.file._file
    self.file = None

    super(MyModel, self).save(*args, **kwargs)

    self.file = old_file

    return super(MyModel, self).save(*args, **kwargs)

当然,这会在您创建新条目时导致对数据库的双重请求,但是我能想出的任何其他解决方案都需要对数据库执行至少一次命中(基于唯一约束的键) ,基于创建日期的关键等。)

希望这有帮助!

答案 1 :(得分:0)

如果您没有尝试最小化字段的大小,那么您提供的第一个选项将是一个很好的选择。如果你的int64 ID最高可达2 ^ 64 - 1(64位整数),你必须在数据库中拥有超过一万亿条目(~2 ^ 40)才能开始担心超过1个查询。如果您正在使用日期时间,那么第二个也不太可能发生,并且如果它发生碰撞,您可以通过操纵日期来防止相同的while循环。

一种选择是拥有一个唯一的ID生成器。您可以将它存储在数据库中,当您要创建FileField时,您可以进行一次查询以获取生成的最后一个ID,增加一个并再次将其保存到db。

另一个选择是手动实现FileField。而不是使用FileField,使用类似CharField的东西,并自己操纵文件的cohersions和路径。