如何在Django中自动生成带INV前缀的递增发票编号
实现自动生成带INV前缀的递增发票编号
1. 修正模型代码错误
你提供的模型存在两处小问题,先修正:
- 继承类应为
models.Model而非model.Models invoice_number字段重复赋值,需删除冗余部分
修正后的基础模型:
from django.db import models class Invoice(models.Model): clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True, null=True) invoice_number = models.CharField(max_length=200, blank=True, null=True)
2. 重写save()方法自动生成编号
在Invoice模型中重写save()方法,实现保存时自动生成格式为INV-XXXX的递增编号:
from django.db import models class Invoice(models.Model): clients_name = models.ForeignKey(Clients, on_delete=models.CASCADE, blank=True, null=True) invoice_number = models.CharField(max_length=200, blank=True, null=True) def save(self, *args, **kwargs): # 仅在新建发票时生成编号(未保存到数据库时self.pk不存在) if not self.pk: # 获取最后一条发票记录,提取序号并递增 last_invoice = Invoice.objects.all().order_by('-id').first() if last_invoice: last_number = int(last_invoice.invoice_number.split('-')[1]) new_number = last_number + 1 else: # 无历史记录时从1开始 new_number = 1 # 格式化序号为4位(如0001),要3位则改为`f'INV-{new_number:03d}'` self.invoice_number = f'INV-{new_number:04d}' super().save(*args, **kwargs)
3. 表单中隐藏发票号字段
在对应的表单类里,将invoice_number设置为隐藏字段,禁止用户手动修改:
from django import forms from .models import Invoice class InvoiceForm(forms.ModelForm): class Meta: model = Invoice fields = ['clients_name', 'invoice_number'] widgets = { 'invoice_number': forms.HiddenInput() }
高并发场景补充
如果系统存在多用户同时创建发票的情况,直接统计数量可能导致编号重复,可改用数据库计数器避免冲突:
# 先创建一个计数器模型(或用单独表存储) class InvoiceCounter(models.Model): count = models.IntegerField(default=0) # 在Invoice的save方法中调用 def save(self, *args, **kwargs): if not self.pk: # 原子操作更新计数器 counter, created = InvoiceCounter.objects.get_or_create(id=1) counter.count += 1 counter.save() self.invoice_number = f'INV-{counter.count:04d}' super().save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者KENnie
相关产品推荐
相关产品推荐

