2015-01-20 4 views
2

Так что я QuerySet обновитьКаков наиболее эффективный способ итерации объектов django, обновляющих их?

stories = Story.objects.filter(introtext="") 
for story in stories: 
    #just set it to the first 'sentence' 
    story.introtext = story.content[0:(story.content.find('.'))] + ".</p>" 
    story.save() 

И операция сохранения() полностью убивает производительность. И в списке процессов есть несколько записей для «./manage.py shell». Да, я запускал это через оболочку django.

Однако в прошлом я запускал сценарии, которые не нужно использовать save(), поскольку он менял много-много полей. Эти скрипты были очень результативными. В моем проекте есть этот код, который может иметь отношение к тому, почему эти сценарии были настолько хороши.

@receiver(signals.m2m_changed, sender=Story.tags.through) 
def save_story(sender, instance, action, reverse, model, pk_set, **kwargs): 
    instance.save() 

Каков наилучший способ эффективного обновления большого набора запросов (10000+)?

ответ

3

насколько новое значение introtext зависит от content поля объекта у ou не может выполнять массовое обновление. Но вы можете ускорить список отдельных объектов сохранения, обернув его в сделке:

from django.db import transaction 

with transaction.atomic(): 
    stories = Story.objects.filter(introtext='') 
    for story in stories: 
     introtext = story.content[0:(story.content.find('.'))] + ".</p>" 
     Story.objects.filter(pk=story.pk).update(introtext=introtext) 

transaction.atomic() увеличит скорость на порядок.

filter(pk=story.pk).update() трюк позволяет предотвратить любые/post_save сигналы pre_save, которые вылетают в случае простого save(). Это officially recommended method обновления одного поля объекта.

+0

Должен ли я изменить этот последний фильтр на get? – straykiwi

+0

Нет, ты не мог. Следуйте ссылке на документацию в своем ответе и читайте: «Если вы просто обновляете запись и ничего не должны делать с объектом модели, наиболее эффективным подходом является вызов update(), а не загрузка объекта модели в память. »« – catavaran

+0

Это было НЕВЕРОЯТНО быстрее. Мне никогда не приходило в голову обернуть одну транзакцию. спасибо – straykiwi

0

Вы можете использовать update встроенные функции по queryset

Exmaple: с

MyModel.objects.all().update(color=red) 

В вашем случае, вам нужно использовать F() (читать далее here) встроенную функцию, чтобы использовать экземпляр собственные атрибуты:

from django.db.models import F 

stories = Story.objects.filter(introtext__exact='') 
stories.update(F('introtext')[0:F('content').find(.)] + ".</p>") 
+0

Но поле, которое я хочу обновить, будет отличаться между экземплярами. Это не статично. Вводный текст примет первое предложение этого содержимого экземпляра. Я также пробовал использовать save (update_fields = ["introtext"]), и это было так же плохой результат wise – straykiwi

+0

AttributeError: 'F' объект не имеет атрибута 'find' – straykiwi

Смежные вопросы