Django select_for_update() для произвольного объекта

#python #django #django-models

#python #django #django-модели

Вопрос:

Я хочу сделать атомарное обновление объекта, тип которого может отличаться. Структура выглядит примерно так:

 class MyMixin(models.Model):
    size = models.BigIntegerField(null=False, default=0)

class SubClassA(MyMixin, models.Model):
    <...>

class SubClassB(MyMixin, models.Model):
    <...>

# obj is of type SubClassA or SubClassB
def some_func(obj):
    with db.transaction.atomic():
        # obj = SubClassA.objects.select_for_update().get(id=obj.id)  # How do I do this?
        obj.size = calculate()
        obj.save()
 

Все примеры, которые я могу найти, явно используют <Class>.objects.select_for_update() шаблон, но моя проблема в том, что я не знаю, каким будет класс во время выполнения. В моем коде у меня уже есть экземпляр объекта / модели, но мне нужно повторно извлечь его из базы данных, чтобы заблокировать его.

Я пытаюсь извлечь идеи из «пессимистического подхода», найденного в этом руководстве — https://medium.com/@hakibenita/how-to-manage-concurrency-in-django-models-b240fed4ee2

Должен ли я использовать очень простой метод, MyMixin который позволяет мне устанавливать и сохранять size ? Или я мог бы явно проверить type obj во время выполнения и иметь кучу elif s (чтобы сделать что-то вроде if/elif type(obj) == SubClassA: SubClassA.objects.select_for_update()... ), но это и уродливо, и не очень удобно в обслуживании.

Ответ №1:

Вы всегда можете получить класс объекта из его __class__ атрибута. Итак:

 obj = obj.__class__.objects.select_for_update().get(id=obj.id)