首页 > 解决方案 > 如何使用预定义的字母部分(Django 模型)声明基于时间的字母数字 id 字段

问题描述

我正在用 Django 开发一个应用程序。

我想在我的模型中插入一个自动递增的字母数字唯一 ID 字段,默认情况下,有一个固定的字母部分和一个自动递增的数字部分。但我也希望可用性从管理部分更改为另一个字母数字 ID,具有不同的字母数字和数字部分。

试图实现这一点,但事实证明,试图实现这样一个字段并使其成为模型的自动字段会在我的数据库中产生问题。

所以我改变了我的目标:现在我想用预定义的字母部分实现一个基于时间的字母数字唯一字段。请注意:我不想覆盖 django 默认 id 字段,我只想在我的模型中包含一个字段,该字段作为默认值获取唯一的自定义字母数字值。

这是我在models.py中所做的:

def return_timestamped_id():
    prefix = "ITCH"    
    import time
    this_time = time.time()
    this_time  = this_time  *10000000
    this_time  = int(this_time)
    timestamp = str(this_time)
    default_value = prefix + timestamp
    return(default_value)

class object_example(models.Model):
    name = models.CharField(max_length=256, blank=True, null=True)    
    Id_generated = models.CharField(max_length=256, blank=False, null=False, unique=True, default=return_timestamped_id())

问题是,当我从管理部分向这个模型添加对象时, Id_generated总是相同的。

我希望return_timestamped_id()每次添加新对象时都会调用该函数。很明显,它只调用一次,然后将相同的返回值传递给Id_generated每个新对象。

如何更改我的代码以便在每次添加新对象时获得不同的时间戳?

标签: pythondjangodjango-modelstimestampunique

解决方案


正如您可能在Django 文档中看到的那样,您可以使用值或可调用对象作为默认值。如果您使用可调用对象(例如函数),那么每次需要默认值时都会调用它。

问题:您正在传递一个值,因为您正在调用您的函数default=return_timestamped_id()。当您的模块(models.py)被导入应用程序时,该函数被调用一次。

解决方案:传递函数本身default=return_timestamped_id

您可以在 django.models.Fields 类中看到相关代码(我的评论):

class Field():
    def __init__(self, ..., default=NOT_PROVIDED,...):
        ...
        self.default = default  # save the default as a member variable
        ...

    def get_default(self):
        """Return the default value for this field."""
        return self._get_default()

    @cached_property
    def _get_default(self):
        if self.has_default():
            if callable(self.default):  # if it is callable, return it
                return self.default
            return lambda: self.default # else wrap in a callable

推荐阅读