Intro:
У меня есть несколько механизмов, сохраняющих данные в одном экземпляре базы данных (postgres), теперь для merchantA идентификатор в его списке ролей: 1,3,4,5,8, для merchantB: 2,6,7,8,10, чтобы каждый продавец мог получить свои собственные идентификаторы последовательного приращения, например, в списке ролей forntend торговца A должно быть:
"merchant_id":1,
"role":{
"id":1,"name":admin,
"id":2,"name":dev,
"id":3,"name":finance,
}
роль продавца B Список:
"merchant_id":2,
"role":{
"id":1,"name":admin,
"id":2,"name":dev,
"id":3,"name":finance,
}
Решение:
Я установил поле ref_id для модели ролей вместо того, чтобы использовать идентификатор поля базы данных по умолчанию, и использую таблицу для сохранения результата подсчета, когда объект роли
class Role(BaseModel):
name = models.CharField(
null=True,
blank=True,
max_length=50
)
ref_id = models.IntegerField(null=True, blank=True)
merchant = models.ForeignKey(Merchant, on_delete=models.CASCADE)
# use pre_save to save the count returned from AutoIDService
@receiver(pre_save, sender=Role)
def update_ref_id(sender, instance: Role, **kwargs):
instance.ref_id = AutoIDService.next('Role', instance.merchant.id)
#IDTable used to save persist count
class IDTable(BaseModel):
key = models.CharField(max_length=255, null=True, blank=True)
ref_id = models.IntegerField(null=True, blank=True)
#do the count, return current
class AutoIDService:
@classmethod
def next(cls, table_name, merchant_id):
key = table_name + str(merchant_id)
with transaction.atomic():
id_table, created = IDTable.objects.select_for_update().get_or_create(key=key, defaults={'ref_id': 1})
print('created', created)
if not created:
print('created false')
id_table.ref_id += 1
id_table.save()
print('return value', id_table.ref_id)
return id_table.ref_id
Задача
#This is the very first record in Role Table
m1 = Merchant.objects.first()
r1 = Role(name='test1',merchant=m1,created_at=datetime.datetime.now())
r1.save()
#when I'm trying to save a role to database, I got this result:
#created True
#value 1
#created False
#created false
#return value 2
# second record for m1
r2 = Role(name='test2',merchant=m1,created_at=datetime.datetime.now())
r2.save()
#created False
#created false
#return value 3
#data in Role table is like
id name ref_id merchant_id
1 test1 2 1
2 test2 3 1
Я не уверен, почему ref_id был посчитан дважды для первой записи, затем я попытался создать роль для другого продавца
r1 = Role(name='test1',merchant=m2,created_at=datetime.datetime.now())
r2 = Role(name='test2',merchant=m2,created_at=datetime.datetime.now())
r1.save()
#created True
#return value 1
r2.save()
#created False
#created false
#return value 2
#data in Role table:
id name ref_id merchant_id
3 test1 1 2
4 test2 2 2
Вопрос
Что произошло в первой записи? и почему запись merchant2 верна? Wi sh кто-то может мне помочь с этим .. и кстати, это лучший способ решить эту проблему? Я также попытался UUID, HashID, но вывод не то, что я хочу.