Django: Инкрементное представление записи в блоге рассчитывает одним. Действительно ли это эффективно?

Прочитайте прямо в выделенное пространство с помощью fgets().

Особое внимание следует уделить распознаванию успешной ошибки чтения, конца файла, ввода и выхода из памяти.

Этот метод сохраняет строку '\n'.

#include <stdio.h>
#include <stdlib.h>

#define FGETS_ALLOC_N 128

char* fgets_alloc(FILE *istream) {
  char* buf = NULL;
  size_t size = 0;
  size_t used = 0;
  do {
    size += FGETS_ALLOC_N;
    char *buf_new = realloc(buf, size);
    if (buf_new == NULL) {
      // Out-of-memory
      free(buf);
      return NULL;
    }
    buf = buf_new;
    if (fgets(&buf[used], (int) (size - used), istream) == NULL) {
      // feof or ferror
      if (used == 0 || ferror(istream)) {
        free(buf);
        buf = NULL;
      }
      return buf;
    }
    size_t length = strlen(&buf[used]);
    if (length + 1 != size - used) break;
    used += length;
  } while (buf[used - 1] != '\n');
  return buf;
}

Использование образца

int main(void) {
  FILE *istream = stdin;
  char *s;
  while ((s = fgets_alloc(istream)) != NULL) {
    printf("'%s'", s);
    free(s);
    fflush(stdout);
  }
  if (ferror(istream)) {
    puts("Input error");
  } else if (feof(istream)) {
    puts("End of file");
  } else {
    puts("Out of memory");
  }
  return 0;
}
22
задан Ty. 15 January 2009 в 15:15
поделиться

5 ответов

Для этого вы можете использовать объекты F () .

Вот как вы импортируете F : из django.db.models import F

Новое в Django 1.1 .
Вызовы для обновления также могут использовать F () объекты для обновления одного поля на основе значения другого поля в модели. Это особенно полезно для увеличения счетчиков на основе их текущего значения.

Entry.objects.filter(is_published=True).update(views=F('views')+1)

Хотя вы не можете выполнить обновление нарезанного набора запросов ... редактировать: на самом деле вы можете ...

Это можно сделать полностью в django ORM. Вам понадобятся два SQL-запроса:

  1. Выполните фильтрацию и соберите список первичных ключей.
  2. Выполните обновление для набора элементов несрезанного запроса, соответствующих любому из этих первичных ключей.

Получение неразрезанного запроса набор - жесткий бит. Я подумал об использовании in_bulk , но это возвращает словарь, не набор запросов. Обычно можно использовать Q объектов для выполнения сложных запросов типа ИЛИ, и это будет работать, но pk__in выполняет эту работу намного проще.

latest_entry_ids = Entry.objects.filter(is_published=True)\
                                      .order_by('-date_published')
                                      .values_list('id', flat=True)[:10]  
non_sliced_query_set = Entry.objects.filter(pk__in=latest_entry_ids)  
n = non_sliced_query_set.update(views=F('views')+1)  
print n or 0, 'items updated'

Из-за того, что django выполняет запросы лениво. , в результате получается всего 2 обращения к базе данных, независимо от того, сколько элементов обновлено.

56
ответ дан 29 November 2019 в 03:30
поделиться

Вы могли обработать обновления в единственной транзакции, которая могла значительно улучшить производительность. Используйте отдельную функцию, украшенную @transaction.commit_manually.

@transaction.commit_manually
def update_latest_entries(latest_entry_list):
    for entry in latest_entry_list:
        entry.views += 1
        entry.save()
    transaction.commit()
13
ответ дан Jeff Bauer 29 November 2019 в 03:30
поделиться

Пересмотренный

Вы обновляете 10 отдельных, отдельных, отдельных объектов.

Эти 10 отдельных, отдельных, отличных обновлений не могут легко быть свернуты в одно волшебное обновление, которое так или иначе касается 10 объектов.

3
ответ дан S.Lott 29 November 2019 в 03:30
поделиться

При реальной необходимости в эффективности в данный момент Вы имели бы к выпадающему в SQL и выполнять обновление сами. Это не стоит добавленной сложности в этом случае, все же.

Django 1.1 Вы будете в состоянии сделать это в единственном вызове SQL через ORM использование F () объекты к полям ссылки в значении обновления.

3
ответ дан Carl Meyer 29 November 2019 в 03:30
поделиться

Улучшение производительности к предыдущей записи. Это приводит к одной базе данных, с помощью подзапросе.

latest_entry_query_set = Entry.objects.filter(is_published=True)
                                      .order_by('-date_published')[:10]  
non_sliced_query_set = Entry.objects.filter(pk__in=latest_entry_query_set.values('id'))  
n = non_sliced_query_set.update(views=F('views')+1)  
print n or 0, 'items updated'
2
ответ дан 29 November 2019 в 03:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: