Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django模型中的自定义Id_Python_Django_Django Models - Fatal编程技术网

Python Django模型中的自定义Id

Python Django模型中的自定义Id,python,django,django-models,Python,Django,Django Models,在我的模型中,我需要一个不同于Django给出的默认ID的ID字段。我需要以下格式的身份证:[年份][升序数字] 示例:2021001,2021002,2021003 ID不可编辑,但模型条目应采用模型中日期时间字段中ID的年份。我不确定我是否使用了一个普通的Django ID,是否还为模型创建了某种附加ID,或者我是否用一个替换了普通的Django ID。这个问题与我之前为一个项目解决的问题非常相似。为此,我所做的只是简单地使用主键的默认id,同时使用一些额外的字段来生成所需的复合标识符 为了

在我的模型中,我需要一个不同于Django给出的默认ID的ID字段。我需要以下格式的身份证:[年份][升序数字]

示例:
2021001
2021002
2021003


ID不可编辑,但模型条目应采用模型中日期时间字段中ID的年份。我不确定我是否使用了一个普通的Django ID,是否还为模型创建了某种附加ID,或者我是否用一个替换了普通的Django ID。

这个问题与我之前为一个项目解决的问题非常相似。为此,我所做的只是简单地使用主键的默认id,同时使用一些额外的字段来生成所需的复合标识符

为了确保计数的唯一性和重新启动,我制作了一个模型,该模型(仅根据逻辑,没有实际约束)中只有一行。每当创建需要此标识符的模型的新实例时,该行将在事务中更新,并使用其存储值

实施情况如下:

from django.db import models, transaction

import datetime


class TokenCounter(models.Model):
    counter = models.IntegerField(default=0)
    last_update = models.DateField(auto_now=True)

    @classmethod
    def get_new_token(cls):
        with transaction.atomic():
            token_counter = cls.objects.select_for_update().first()
            if token_counter is None:
                token_counter = cls.objects.create()
            if token_counter.last_update.year != datetime.date.today().year:
                token_counter.counter = 0
            token_counter.counter += 1
            token_counter.save()
            return_value = token_counter.counter
        return return_value

    def save(self, *args, **kwargs):
        if self.pk:
            self.__class__.objects.exclude(pk=self.pk).delete()
        super().save(*args, **kwargs)
接下来,假设您需要在其他模型中使用此选项:

class YourModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    yearly_token = models.IntegerField(default=TokenCounter.get_new_token)

    @property
    def token_number(self):
        return '{}{}'.format(self.created_at.year, str(self.yearly_token).zfill(4))
    
    @classmethod
    def get_from_token(cls, token):
        year = int(token[:4])
        yearly_token = int(token[4:])
        try:
            obj = cls.objects.get(created_at__year=year, yearly_token=yearly_token)
        except cls.DoesNotExist:
            obj = None
        return obj

注意:这可能不是很精确,因为代码是在我非常缺乏经验的时候编写的,可能有很多地方可以改进。例如,您可以在
year\u token
字段中添加一个
unique\u For\u year
,以便:

yearly_token = models.IntegerField(default=TokenCounter.get_new_token, unique_for_year='created_at')