Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Это - определенный взлом. Необработанный SQL сделает Ваш код менее портативным, но это избавится от состояния состязания на встречном инкременте. В теории это должно увеличить счетчик любое время, Вы делаете запрос. Я не протестировал это, таким образом, необходимо удостовериться, что список интерполирован в запросе правильно.
class VisitorDayTypeCounterManager(models.Manager):
def get_query_set(self):
qs = super(VisitorDayTypeCounterManager, self).get_query_set()
from django.db import connection
cursor = connection.cursor()
pk_list = qs.values_list('id', flat=True)
cursor.execute('UPDATE table_name SET counter = counter + 1 WHERE id IN %s', [pk_list])
return qs
class VisitorDayTypeCounter(models.Model):
...
objects = VisitorDayTypeCounterManager()
Если Вы действительно хотите в противоречии с, точны, Вы могли бы использовать транзакцию, но сумма требуемого параллелизма действительно ослабит Ваше приложение и базу данных при любой значительной загрузке. Вместо этого думайте о движении с большим количеством обменивающегося сообщениями подхода стиля и просто ведите учет количества дампа в таблицу для каждого посещения, где Вы хотели бы увеличить счетчик. Тогда, когда Вы хотите общее количество посещений, проводят подсчет на таблице посещений. У Вас мог также быть фоновый процесс, который выполнил любое количество раз день, который суммирует посещения и затем сохранит это в родительской таблице. Чтобы экономить на пространстве, это также удалило бы любые записи из дочерней таблицы посещений, которой это подвело итог. Вы сократите свои затраты параллелизма огромная сумма, если у Вас не будет нескольких агентов, соперничающих за те же ресурсы (счетчик).
Можно использовать патч от http://code.djangoproject.com/ticket/2705 для блокировки уровня базы данных поддержки.
С патчем этот код будет атомарным:
visitors = VisitorDayTypeCounter.objects.get(day=curday).for_update()
visitors.counter += 1
visitors.save()
Почему бы не использовать базу данных в качестве слоя параллелизма? Добавьте первичный ключ или ограничение на уникальность данных таблица к visitType и visitDate. Если я не ошибаюсь, django точно не поддерживает это в их классе модели базы данных, или по крайней мере я не видел примера.
, Как только Вы добавили ограничение/ключ к таблице, тогда все, которое необходимо сделать:
Это противно, чтобы сделать это этот путь, но это кажется достаточно быстрым и покрыло бы большинство ситуаций.
Два предложения:
Добавляют unique_together к Вашей модели и обертывают создание в обработчик исключений для ловли дубликатов:
class VisitorDayTypeCounter(models.Model):
visitType = models.CharField(max_length=60)
visitDate = models.DateField('Visit Date')
counter = models.IntegerField()
class Meta:
unique_together = (('visitType', 'visitDate'))
После этого у Вас могло все еще быть незначительное состояние состязания на обновлении счетчика. Если бы Вы заставляете достаточно трафика быть затронутым, о котором, я предложил бы изучить транзакции для более прекрасного гранулярного управления базой данных. Я не думаю, что ORM имеет прямую поддержку блокировки/синхронизации. Документация транзакции доступна здесь .
Ваш должен использовать транзакции базы данных для предотвращения этого вида состояния состязания. Транзакция позволяет Вам выполнить целую операцию создания, чтения, постепенного увеличения и сохранения счетчика на "все или ничего" основа. Если что-нибудь пойдет не так, как надо, то это будет откатывать все это, и можно попробовать еще раз.
Выезд Django документы. существует изделие середины транзакции, или можно использовать декораторов вокруг представлений или методов для создания транзакций.
Начиная с Django 1.1 вы можете использовать выражения F () ORM.
from django.db.models import F
product = Product.objects.get(name='Venezuelan Beaver Cheese')
product.number_sold = F('number_sold') + 1
product.save()
Подробнее см. Документацию:
https: //docs.djangoproject.com/en/1.8/ref/models/expressions/#django.db.models.F[1247pting