【问题标题】:How to declare a auto-incrementing alphanumerical id field with predefined aplphabetic part (Django python)如何使用预定义的字母部分(Django python)声明一个自动递增的字母数字 id 字段
【发布时间】:2020-05-23 13:41:45
【问题描述】:

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

我想在我的模型中插入一个自动递增的字母数字 ID 字段,默认情况下具有固定的字母部分和自动递增的数字部分。
但我也希望可用性从管理部分更改为另一个字母数字的,具有不同的字母数字和数字部分。
请注意:我不想覆盖 django默认 id 字段,我只想在我的模型中包含一个字段,该字段将默认值作为自动递增的字母数字值。

我想要的示例:

  • 所需的字母常量部分:ITM

  • 所需的数值自增部分:00000

    这样我的模型的每个对象,在生成时,都是默认的 渐进值,例如:ITM00001、ITM00002、ITM00003、...

  • 另外,我希望能够从我的管理员更改字段值 分段为 ABC0000001、DFG0051、RST034、...等值

  • 最大字段长度:10(也可以更高)

我意识到我必须使用AutoField 并以某种方式将常量字符串与自动递增的数值变量连接起来,但我不知道该怎么做。

class my_model(models.Model):

    Field_1 = models.CharField(max_length=10, blank=True, null=True)
    static_ID = models.AutoField(???)

我应该编写什么代码来获得具有我上面描述的功能的字段?

【问题讨论】:

    标签: python django django-models auto-increment autofield


    【解决方案1】:

    也许您可以将您的字段分成三个单独的字段:

    class MyModel(models.Model):
        PREF = "ITM"
        NUMS = 5
    
        field1 = models.CharField(max_length=10, blank=True, null=True)
        ...
        pref = models.CharField(max_length=3, default=PREF)  # prefix that has defaul value and can be modified
        nums = models.PositiveIntegerField(default=NUMS)  # the number of digits
        static_id = models.AutoField(primary_key=False)  # auto increment field
    
        class Meta:
            unique_together = ('pref', 'nums', 'static_id')
    
        @property
        def static_key(self):
            return self.pref + str(self.static_id).zfill(self.nums)
    

    【讨论】:

    • 我遇到错误 assert not cls._meta.auto_field,“模型 %s 不能有多个 AutoField。” % cls._meta.label AssertionError:模型 my_app.my_model 不能有多个 AutoField。显然,每个 django 模型必须不超过一个 AutoField 所以我不得不设置 static_id = models.AutoField(primary_key=True)
    • 我不想走这条路,因为通过覆盖 django 默认 ID 通常会产生管理员管理该 ID 的问题。
    【解决方案2】:

    为什么不使用属性方法来生成该id,而不是存储它?例如:

    class MyModel(models.Model):
    
        field_one = models.CharField(max_length=10, blank=True, null=True)
        
        @property
        def static_id(self):
            'ITM{0:07d}'.format(self.pk)
    

    如果你关心过滤,那么你可以使用custom manager method

    class CustomManager(models.Manager):
        def get_id(self, static_id):
            return int(static_id[2:])
        def filter_static_id(self, static_id):
            _id = self.get_id(static_id)
            return self.filter(pk=_id)
        
      def filter_static_id(self, static_id):
            _id = self.get_id(static_id)
            return self.get(pk=_id)
    
     class MyModel(models.Model):
          objects = CustomManager()
       
    

    【讨论】:

    • 这个类 MyModel(models.Model): field_one = models.CharField(max_length=10, blank=True, null=True) @property def static_id(self): 'ITM{0:07d} '.format(self.pk) 让我遇到错误:django.core.exceptions.FieldError: Unknown field(s) (static_id) specified for my_model
    • 你从哪里得到错误?你能添加完整的错误 stacttrace 吗?
    【解决方案3】:

    已解决:

    由于我的 id 不需要特定长度,也不需要两个连续 id 之间的恒定增量,因此我可以使用 time.time() 来在每次创建模型中的对象时获取唯一的时间编号。然后我可以把那个时间数字变成一个字符串,并用一个常量前缀连接它。

    models.py 中:

    import time
    
    def return_timestamped_id():
        prefix = "ITCH"     
        timestamp = str(int(time.time()*10000000))
        default_value = prefix + timestamp
        return(default_value)
    
    
    class my_model(models.Model):        
        Field_1 = models.CharField(max_length=256)
        static_ID = models.CharField(max_length=256, blank=False, null=False, default=return_timestamped_id)
    

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      相关资源
      最近更新 更多