Автоинкремент поля, зависящего от количества появлений определенного значения в 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 будет номер вашего клиента.