2013-10-12 2 views
3

У меня есть ListView с пагинацией:Джанго: производительность базы данных постраничной ListView

class StoriesListView(ListView): 
    model = Story 
    paginate_by = 20 

    def get_queryset(self): 
     return Story.objects.all().order_by('-updated_at') 

У меня есть 1000 Story объектов в базе данных. Что происходит, когда пользователь загружает мой просмотр? Будут ли запрашиваться все 1000 из базы данных или всего 20? Как я могу это оптимизировать?

ответ

5

это зависит от того, как вы его используете. Объекты QuerySet: lazy, и в этом конкретном случае запрос sql добавит LIMIT и OFFSET, поэтому запрос всегда будет возвращать только 20 результатов. Но когда вы хотите использовать, например, связанные объекты в своем шаблоне, вы должны оптимизировать свой запрос с помощью методов select_related или prefetch_related.

Я думаю, что вы должны прочитать как optimize database access в каркасе django.

Надеюсь, это поможет.

0

Он получит только 20 объектов. Paginator принимает результат метода get_queryset как начало запроса, и он будет удалять базу данных только при повторении, чтобы вы были хороши. Метод get_queryset не попадает в сам db.

2

Класс Paginator принимает возвращаемое значение get_queryset (т. Е. Весь запрос в этом случае) и соединяет его, чтобы предоставить вам доступ только к 20. Он должен работать на всем запросе, иначе вы не сможете использовать он должен отображать список страниц, например.

Вы можете увидеть следовать код, чтобы увидеть его в действии:

get()>get_context_data()>paginate_queryset()> Paginator.init()

Это означает, что in your template context, переменная queryset является весь QuerySet. Переменная page используется для получения только тех объектов, которые принадлежат текущей странице. Это делается splicing the initial queryset, который будет оценивать его и попадать в БД. Вы можете перебирать объекты в этой странице: {% for object in page %} и это не будет снова попал в базу данных:

# https://github.com/django/django/blob/master/django/core/paginator.py#L119 
def __getitem__(self, index): 
    if not isinstance(index, (slice,) + six.integer_types): 
     raise TypeError 
    # The object_list is converted to a list so that if it was a QuerySet 
    # it won't be a database hit per __getitem__. 
    if not isinstance(self.object_list, list): 
     self.object_list = list(self.object_list) 
    return self.object_list[index] 
-3

Та же проблема я принес во пагинацией. Для разбивки на страницы вам не нужно делать функцию внутри модальной.

вы можете использовать Нт же думать можно сделать, просто мою обобщает функцию

Защита testPagination (запрос):

dataObj    = paginationData('Item',page_no,10) 
data["dataIndex"] = dataObj["dataIndex"] 
data["page_no"]  = dataObj["page_no"] #given page number will helps to active link at template 
data["data"]  = dataObj["data"] #actual data will helps in template 
data['pagination'] = dataObj["pagination"] #Will helps to make dynamic link for pagination 

обобщать PAGINATION ФУНКЦИЯ

def paginationData(modalName,pageNo,perPage): 
    data = {} #initialize variables 
    Modal = getModel(modalName) # Function to get modal reference 
    count = Modal.objects.count()#Calculate no of records 
    no_of_record_per_page = ceil(float(count)/perPage) 
    print ",Records counts : " + str(no_of_record_per_page) 
    pages = [] #No of pages 
    pages.append(1) 
    a = 1 
    while a < (no_of_record_per_page): 
     a += 1 # Same as a = a + 1 
     pages.append(a) 
    data["pagination"] = pages # pagenation for display link of page 
    data["page_no"] = pageNo 
    data['data'] = Modal.objects.all()[((pageNo-1)*perPage):(pageNo*perPage)] 
    data['dataIndex'] = str((pageNo -1)*perPage) 
    return data 
Смежные вопросы