Django_07 batch insert and pager

Posted by morgann7 on Sun, 06 Feb 2022 03:34:20 +0100

1. Batch insert

def ab_pl(request):
    # Insert 10000 pieces of data into the Book first
    # for i in range(10000):
    #     models.Book.objects.create(title = 'Book% s'% i)
    # # Then query and display all the data to the front page
    book_queryset = models.Book.objects.all()

    # Batch insert
    # book_list = []
    # for i in range(100000):
    #     book_obj = models.Book(title = 'Book% s'% i)
    #     book_list.append(book_obj)
    # models.Book.objects.bulk_create(book_list)
    """
    Use when you want to insert data in batches orm For you bulk_create It can greatly reduce the operation time
    :param request: 
    :return: 
    """
    return render(request,'ab_pl.html',locals())

Single operation has a great impact on performance.

2. Pager

2.1 analysis

Total data 100, 10 per page
Total data 101 display 10 per page requires 11
Total data 99 10 per page

How to dynamically calculate how many pages are needed through code?
When making the number of pages, it is usually an odd number It meets the standard of symmetrical beauty of the Chinese people

2.2 derivation

To customize the pager, you need to do the following

1.queryset objects are sliced directly

2. How to determine which page users want to visit? url?page=1

current_page = request.GET.get('page',1)
The data obtained is of string type. You need to pay attention to type conversion

3. Specify how many pieces of data are displayed on each page

per_page_num = 10

4. Start and end positions of slices

start_page = (current_page - 1)* per_page_num
end_page = current_page * per_page_num
Find out the law of the above four parameters by using the simple law

5. Total number of current data

book_queryset.count()

6. How to determine the total number of pages required to display all the data

Using python built-in function divmod()
page_count, more = divmod(all_count,per_page_num)
if more:
page_count += 1

7. The front-end template syntax has no range function

The front-end code does not have to be written at the front-end, but can also be generated at the back-end and passed to the page

8. For the pages to be displayed, you need to plan how many pages to display

In general, the number of pages is designed to be an odd number (in line with aesthetic standards) of 11 pages
Current page minus 5
Current page plus 6
You can give the tag a price style to highlight the selected page number

9. If the page number is less than 6, you need to deal with it. You can't reduce it any more

2.3 simple code of custom pager

book_list = models.Book.objects.all()

# Which page do you want to visit
current_page = request.GET.get('page',1)  # If the current page number cannot be obtained, the first page will be displayed
# Data type conversion
try:
    current_page = int(current_page)
except Exception:
    current_page = 1
# How many are displayed on each page
per_page_num = 10
# Starting position
start_page = (current_page - 1) * per_page_num
# End position
end_page = current_page * per_page_num

# Figure out how many pages are needed
all_count = book_list.count()

page_count, more = divmod(all_count, per_page_num)
if more:
    page_count += 1

page_html = ''
xxx = current_page
if current_page < 6:
    current_page = 6
for i in range(current_page-5,current_page+6):
    if xxx == i:
        page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i)
    else:
        page_html += '<li><a href="?page=%s">%s</a></li>'%(i,i)

book_queryset =  book_list[start_page:end_page]

django has its own pager module, but it is troublesome to write and the function is too simple
So we think and try our best to write a custom pager

2.4 packaging

Pager class

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        Encapsulate paging related data
        :param current_page: Current page
        :param all_count:    Total number of data in the database
        :param per_page_num: Number of data pieces displayed per page
        :param pager_count:  Maximum number of page numbers displayed
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # Total page number
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # If total pages < 11:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # Total page > 11
        else:
            # If the current page is < = at most 11 / 2 page numbers are displayed on the page
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # The current page is larger than 5
            else:
                # Page number last
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # Add the previous nav and ul tags
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">home page</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#"> previous page < / a > < / Li > '
        else:
            prev_page = '<li><a href="?page=%s">previous page</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#"> next page < / a > < / Li > '
        else:
            next_page = '<li><a href="?page=%s">next page</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">Last page</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # Add label to tail
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

Use of pager class

back-end

def get_book(request):
    book_list = models.Book.objects.all()
    current_page = request.GET.get("page",1)
    all_count = book_list.count()
    page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
    page_queryset = book_list[page_obj.start:page_obj.end]
    return render(request,'booklist.html',locals())

front end

<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>