Django select_for_update () для произвольного объекта - PullRequest
0 голосов
/ 18 апреля 2019

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

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 Ответ

2 голосов
/ 18 апреля 2019

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

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