Автоинкремент поля, зависящего от количества появлений определенного значения в django

Я ищу хороший пример или совет для решения моей проблемы в Django & python. У меня есть простая модель типа Customer

class Customer(models.Model):
    customer_name = models.CharField(max_length=500)
    CUSTOMER_CHOICES = [
        ('pc', 'Private Customer'),
        ('bc', 'Business Customer'),
    ]
    customer_type = models.CharField(max_length=2, choices=CUSTOMER_CHOICES)

Для всех клиентов я хочу создать (и показать на странице) определенный "Номер клиента", основанный на типе клиента и десятичном числе. Я думаю, что могу хранить это значение в таблице Customer (что-то вроде этого):

|id|customer_name|customer_type|customer_number|
|1 |Private 1    |pc           |1              |
|2 |Private 2    |pc           |2              |
|3 |Business 1   |bc           |1              |
|4 |Private 3    |pc           |3              |
|5 |Business 2   |bc           |2              |    

Конечно, когда я буду изменять имя клиента или другое значение (кроме типа клиента и номера клиента), я не хочу обновлять этот номер.

Возможно ли избежать пробелов в номерах или дублирования номеров? Я думаю, что приведенный ниже код не будет работать (это просто пример, как первая мысль), потому что я не знаю, как код будет работать, когда у меня будет две разные сессии и когда я нажму кнопку сохранения одновременно.

def save():
    if customer_number is None:
        last_number = Customer.objects.all().filter(customer_type=passed_type).last()

    #bellow in the pseudocode
        new_invoice_number = last_number.customer_number + 1
        save object

Есть ли в Django какие-либо инструменты, чтобы сделать это действительно хорошо?

В Django нет ни одного конкретного инструмента для достижения вашего результата. Вот два варианта.

1. Метод Save(). В принципе, это ваш подход. Но его следует объединить с методом Django UniqueConstraint.condition (docs), чтобы убедиться, что поле customer_number уникально для каждого типа клиента. Ограничения модели могут быть установлены как meta option.

class Customer(models.Model):
    customer_name = models.CharField(max_length=500)
    CUSTOMER_CHOICES = [
        ('pc', 'Private Customer'),
        ('bc', 'Business Customer'),
    ]
    customer_type = models.CharField(max_length=2, choices=CUSTOMER_CHOICES)

    class Meta:
        constraints = [
            models.UniqueConstrained(fields=['customer_number'], condition=Q(customer_type='pc'), name='unique_pc_customer'),
            models.UniqueConstrained(fields=['customer_number'], condition=Q(customer_type='bc'), name='unique_bc_customer'),
            ]

Если ограничение нарушено, выдается сообщение IntegrityError. Вы можете обработать ошибку в методе save() вашей модели.

def save():
    try:
       #Set your customer_number
    except IntegrityError:
       #Handle the error as you wish

2. Отдельные модели Вы можете определить две дополнительные модели, одну для pc, другую для bc. Эти модели будут связаны с вашей моделью Customer один к одному. Идентификатором экземпляра модели pc и экземпляра модели bc будет номер вашего клиента.

Вернуться на верх