Как обновить значения объекта в Django? - PullRequest
25 голосов
/ 20 марта 2012

У меня есть модельный объект в Джанго.Один из методов объекта использует блокировку на уровне строк для обеспечения точности значений, например:

class Foo(model.Model):
    counter = models.IntegerField()

    @transaction.commit_on_success
    def increment(self):
        x = Foo.objects.raw("SELECT * from fooapp_foo WHERE id = %s FOR UPDATE", [self.id])[0]
        x.counter += 1
        x.save()

Проблема в том, что если вы вызываете increment для объекта foo, значения объекта больше не отражаютзначения в базе данных.Мне нужен способ обновить значения в объекте или, по крайней мере, пометить их как устаревшие, чтобы они при необходимости обновлялись.По-видимому, это функциональность, которую разработчики Django отказываются добавлять .

. Я попытался использовать следующий код:

for field in self.__class__._meta.get_all_field_names():
    setattr(self, field, getattr(offer, field)) 

К сожалению, у меня есть вторая модель сследующее определение:

class Bar(model.Model):
    foo = models.ForeignKey(Foo)

Это вызывает ошибку, потому что это появляется в списке полей, но вы не можете getattr или setattr это.

У меня есть два вопроса:

  • Как обновить значения на моем объекте?

  • Нужно ли беспокоиться об обновлении каких-либо объектовсо ссылками на мой объект, как внешние ключи?

Ответы [ 11 ]

0 голосов
/ 20 марта 2012

Я понимаю, почему вы используете SELECT ... FOR UPDATE, но после того, как вы его выпустили, вы все равно должны взаимодействовать с self.

Например, попробуйте это вместо:

@transaction.commit_on_success
def increment(self):
    Foo.objects.raw("SELECT id from fooapp_foo WHERE id = %s FOR UPDATE", [self.id])[0]
    self.counter += 1
    self.save()

Строка заблокирована, но теперь взаимодействие происходит в экземпляре в памяти, поэтому изменения остаются в синхронизации.

...