Django:保存模型时生成自定义序列号

问题描述

我是 Django 的新手。

我有一个 Item 模型,它有一个 property_number 字段和一个 FK location 字段到 Location 模型。 property_number 的格式类似于 0000-00-00-0000-00,即 [year] - [sub account] - [gl account] - [series number] - [位置代码]。在series_number的格式下,这应该是根据参数location_code保存后生成的。

示例:

位置代码 10

Item 1

property number should be: 2021 - 01 - 01 - 0001 - 10

Item 2

property number should be: 2021 - 01 - 01 - 0002 - 10

Item 3

property number should be: 2021 - 01 - 01 - 0003 - 10 ... 等等,

property number should be: 2021 - 01 - 01 - 1000 - 10

位置代码 50

Item 1

property number should be: 2021 - 01 - 01 - 0001 - 50

Item 2

property number should be: 2021 - 01 - 01 - 0002 - 50 ... 等等,

property number should be: 2021 - 01 - 01 - 0055 - 50

位置代码 65

Item 1

property number should be: 2021 - 01 - 01 - 0001 - 65 ... 等等,

property number should be: 2021 - 01 - 01 - 0100 - 65

*在此示例中,对于位置代码 10商品 1、商品 2 和商品 3 具有序列号 0001、0002 和 0003 em>

对于位置代码 50项目 1 和项目 2 的编号系列为 0001 和 0002

等等

每次用不同的位置码保存一个新的Item时,number_series将被重置为0001,当新的Item用相同的位置码保存时会继续

我目前所拥有的

我已经可以通过覆盖 save 函数来保存格式,但我不知道如何生成所需的序列号。

def save(self,*args,**kwargs):
    self.property_number = '{}-{}-{}-{}'.format(self.date_acquired.year,self.sub_major_group_and_gl_account.sub_major_group_and_gl_account,'This is where the series_number is place',self.location.location_code)
    super(Item,self).save(*args,**kwargs)

这是我迄今为止生成series_number,但这当然是不正确的。我也不知道如何比较新的要保存的数据和已经保存的数据。

def generate_series_number(self):
    # Get all records and filter by location.location_code and should be compare if there is already a data that has the same location_code
    get_item_location = Item.objects.all().filter(self.location.location_code=='This should be the latest data to be save')

    # Count how many data has the same location_code to kNow what number series to be assigned
    # if result is,there are already 50 records exist with location_code = '01',the new data will have the series number '51' 
    count_current_data = get_item_location.count()
    assign_series_number = count_current_data + 1

    return assign_series_number

# I will use the 'generate_series_number' function in the save function to format my Property_number field in the model.
def save(self,'series_number',**kwargs)

这是我的 Item 模型

class Item(models.Model):
    item                    = models.CharField(max_length=100,null=True)
    description             = models.TextField(max_length=200,null=True)
    date_acquired           = models.DateField(null=True)
    old_property_number     = models.CharField(max_length=100,null=True)
    property_number         = models.CharField(max_length=100,null=True,blank=True)
    unit_of_measure         = models.ForeignKey('Uom',related_name='uom_item',on_delete=models.SET_NULL)
    unit_value              = models.DecimalField(max_digits=12,decimal_places=2,null=True)
    quantity_per_card           = models.CharField(max_length=100,default='1')
    quantity_per_physical_count = models.CharField(max_length=100,default='1' )
    # location_code as primary key
    location                    = models.ForeignKey('Location',related_name='location_item',on_delete=models.SET_NULL)
    condition                   = models.ForeignKey('Condition',related_name='condition_item',on_delete=models.SET_NULL)
    accountable_person          = models.ForeignKey('Personnel',related_name='personnel_item',on_delete=models.SET_NULL)
    remarks                     = models.ForeignKey('Remarks',related_name='remarks_item',on_delete=models.SET_NULL)
    sub_major_group_and_gl_account    = models.ForeignKey('Account',related_name='sub_major_group_and_gl_account_item',on_delete=models.SET_NULL)

注意:我没有 view.py,我只在管理站点内工作。

我是 Django 新手,不要生我的气:) 提前致谢。

解决方法

我正在回答我自己的问题。

我设法使用以下 save 函数解决了我的问题。 如果有人可以改进我的解决方案,我将不胜感激。

注意:这仅适用于通过管理站点新添加的实例,如果实例是通过 django-import-export 导入的,则将不起作用。因此,这将是我剩下的问题,在管理站点中使用导入功能时为每个实例自动分配 data_counter

否则,将在 excel 文件中手动进行分配。 XD

def save(self,*args,**kwargs):
    data_counter = Item.objects.filter(location=self.location).aggregate(counter=Count('id'))['counter'] # Count existing instance with matching "location id" of the new instance
    if self.pk is None and self.property_number is None: # if new instance and property number field is blank
        if data_counter is None: # if data_counter is empty/none,no matching instance
            data_counter = 1  # start at 1
        else: # else,if there is matching instance
            data_counter += 1 # add 1 to the data_counter
    elif self.pk is not None and self.property_number is None: # if not new instance and property number field is blank,Update an instance without property number
        if data_counter is None: # if data_counter is empty/none,the existing instance has no matching location id,Update
            data_counter = 1 # Existing instance start at 1
        else: # else,if there is matching instance
            data_counter += 1 # add 1 to the data_counter

    # data_counter will be the series number for every location ID
    self.property_number = '{}-{}-{:04d}-{}'.format(self.date_acquired.year,self.sub_major_group_and_gl_account.sub_major_group_and_gl_account,data_counter,self.location.location_code)
    
    super(Item,self).save(*args,**kwargs)