【问题标题】:Generate an unique identifier for a Model为模型生成唯一标识符
【发布时间】:2011-02-10 22:14:14
【问题描述】:

我有一个包含 FileField 的模型。 我希望这个 FileField 有一个唯一的路径。

一开始,虽然关于使用条目的ID,但是Django将文件移动到它的upload_to路径保存条目之前,所以ID是空的。

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

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

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

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

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

【问题讨论】:

    标签: django unique


    【解决方案1】:

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

    这里是代码

    # 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)
    

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

    希望这会有所帮助!

    【讨论】:

    • 我也面临同样的问题...为什么不使用 UNIX 时间的唯一标识符(以毫秒为单位)? (或者如果您认为您会遇到完全相同时间提交的冲突,则以纳秒为单位?) $ date +%s%3N 将为您提供以毫秒为单位的 unix 时间(纳秒被截断为最后 3 位有效数字)。另外,这篇文章可能会有所帮助:stackoverflow.com/questions/1259219/…
    • 既然我重新发现了这个问题,我会建议通过先保存,然后移动文件来覆盖 Django 的保存方法来回答自己,这样可以轻松正确地解决我的问题;)
    【解决方案2】:

    如果您不尝试最小化字段的大小,那么您给出的第一个选项将是一个不错的选择。如果您有一个高达 2^64 - 1(64 位整数)的 int64 ID,那么您的数据库中必须有超过一万亿个条目(〜 2^40),然后您才能开始担心制作过程超过 1 个查询。如果您使用日期时间,则第二个也不太可能发生,并且您可以通过在发生冲突时操作日期来使用相同的 while 循环来防止这种情况发生。

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

    另一种选择是手动实现 FileField。不要使用 FileField,而是使用 CharField 之类的东西并自己操作文件内聚和路径。

    【讨论】:

    • 对不起,我忘了提到路径将在网址中使用。这就是为什么我想在唯一 ID 中使用最小的尺寸。我想我会根据日期使用一些东西并减少它(比如在 hexa 或完全 a-z 中:我取接下来的两个值,如果有 > 26,我只取一个。我将它们转换为它们的字母等价物,一直持续到最后。你觉得呢?
    猜你喜欢
    • 2017-10-20
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多