Имея эту проблему и найдя два окончательных решения, я подумал, что стоит опубликовать другой ответ.
Это проблема в режиме транзакций по умолчанию в MySQL.Django открывает транзакцию при запуске, что означает, что по умолчанию вы не увидите изменений, внесенных в базу данных.
Продемонстрируйте, как это
Запустите оболочку django в терминале 1
>>> MyModel.objects.get(id=1).my_field
u'old'
И еще один в терминале 2
>>> MyModel.objects.get(id=1).my_field
u'old'
>>> a = MyModel.objects.get(id=1)
>>> a.my_field = "NEW"
>>> a.save()
>>> MyModel.objects.get(id=1).my_field
u'NEW'
>>>
Вернемся к терминалу 1, чтобы продемонстрировать проблему - мы все еще читаем старое значение из базы данных.
>>> MyModel.objects.get(id=1).my_field
u'old'
Сейчас в терминале1 демонстрирует решение
>>> from django.db import transaction
>>>
>>> @transaction.commit_manually
... def flush_transaction():
... transaction.commit()
...
>>> MyModel.objects.get(id=1).my_field
u'old'
>>> flush_transaction()
>>> MyModel.objects.get(id=1).my_field
u'NEW'
>>>
Новые данные теперь считываются
Вот этот код в легко вставляемом блоке с строкой документации
from django.db import transaction
@transaction.commit_manually
def flush_transaction():
"""
Flush the current transaction so we don't read stale data
Use in long running processes to make sure fresh data is read from
the database. This is a problem with MySQL and the default
transaction mode. You can fix it by setting
"transaction-isolation = READ-COMMITTED" in my.cnf or by calling
this function at the appropriate moment
"""
transaction.commit()
Альтернативное решение:изменить my.cnf для MySQL, чтобы изменить режим транзакции по умолчанию
transaction-isolation = READ-COMMITTED
Обратите внимание, что это относительно новая функция для Mysql и имеет некоторые последствия для двоичной регистрации / подчинения .Вы также можете добавить это в преамбулу подключения django, если хотите.
Обновление через 3 года
Теперь, когда в Django 1.6 включена , включена автокоммит в MySQL это больше не проблема.Приведенный выше пример теперь отлично работает без кода flush_transaction()
независимо от того, находится ли ваш MySQL в режиме изоляции транзакций REPEATABLE-READ
(по умолчанию) или READ-COMMITTED
.
Что происходило в предыдущих версиях Django, которые работали вРежим autocommit состоял в том, что первый оператор select
открыл транзакцию.Поскольку режим MySQL по умолчанию - REPEATABLE-READ
, это означает, что последующие операторы select
не будут считывать обновления базы данных - следовательно, необходим код flush_transaction()
, описанный выше, который останавливает транзакцию и запускает новую.
Есть еще причины, по которым вы можете использовать READ-COMMITTED
изоляцию транзакций.Если вы хотите включить в транзакцию терминал 1 и хотите видеть записи из терминала 2, вам потребуется READ-COMMITTED
.
Код flush_transaction()
теперь выдает предупреждение об устаревании в Django 1.6, поэтому я рекомендуювы удалите его.