◢Django self-written paging and usage

Table of Contents

1. Set the paging style and display it to the browser

2. Simulate page number

3. Generate paging

4. Data display

5. Previous pageNext page

6. Database data paging

7. Package paging

8. Use encapsulated paging

After building the app, set the path path(‘in2/’, views.in2), view def in2(request): , HTML: in2.html

1. Set the paging style and display it to the browser

def in2(request):
    return render(request,'in2.html')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding: 0;
            list-style: none;
            margin: 0;
        }
        span{

            display: inline-block;
            width: 40px;
            text-align: center;
            font-size: 20px;
            border: 1px solid;
            background-color: #2aabd2;
        }
        a{
            text-decoration: none;
            color: white;
        }
    </style>
</head>
<body>
    <span><a>1</a></span>
</body>
</html>

2. Simulation page number

def in2(request):
    # Assume there are 100 pieces of data
    data_count = 100 #350
    #Each page has 8 pieces of data
    page_size = 8
    #How many pages are there?
    page_count, count=divmod(data_count,page_size)
    if count:
        page_count + =1

    page_string = ''
    for i in range(page_count):
        page_string + =f"<span><a>{i}</a></span>"
        
    #page_string = mark_safe("".join(page_string))
    return render(request,'in2.html',{"page_string":page_string})

If page_string is imported directly into html, it is a string.

The page_string generated by the loop needs to be processed, [Uncomment]

page_string = mark_safe("".join(page_string))

Its function is to concatenate the elements in the string list (`page_string`) and mark the result as safe HTML content. Use the `join()` function to join all the elements in the string list together, and then the `mark_safe()` function marks the connected string as safe, so that when the HTML content is displayed, the elements in it will not be Tags and special characters are escaped. Typically used to generate dynamic HTML content in templates to avoid escaping HTML tags and special characters.

3. Generate paging

As the amount of data increases, the number of pages increases. It is necessary to set the displayed paging. Based on the current page, the first 5 pages and the next 5 pages are displayed. The extra page numbers are not displayed.

Attach parameter page to each a tag, use string concatenation, and use a for loop to indicate the parameters attached to each a.

Click the a tag to send a get request. When the GET request does not obtain the page, it defaults to the first page. After clicking, the url automatically carries the page parameter. Each time you click, the page parameter carried by the a tag is obtained and used as the current page.

def in2(request):
    #The current page is set to 1 by default. If there is a current page passed by the get request, change it.
    
    if request.GET.get('page'):
        current_page = int(request.GET.get('page'))
    else:
        current_page = 1

    data_count = 350
    page_size = 8
    page_count, count=divmod(data_count,page_size)
    if count:
        page_count + =1


    #Set the number of visible pages before and after the current page to 5
    plus=5
    #The current page is less than or equal to 5, the starting page is always 1; the current page is greater than 5, the starting page is the current page minus 5
    if current_page <= plus + 1:
        start_page = 1
    else:
        start_page = current_page - plus
    # If the current page is greater than or equal to the final page, the end page is always the end page; if the current page is less than the end page minus 5, the end page is the current page + 5
    if current_page >= page_count - plus:
        end_page = page_count
    else:
        end_page = current_page + plus


    page_string = ''
    for i in range(start_page, end_page + 1):
        page_string + = f"<span><a href=?page={i}>{i}</a></span>"

    page_string = mark_safe("".join(page_string))
    context={
        "current_page":current_page,
        "start_page":start_page,
        "end_page" :end_page,
        "page_string":page_string,
    }
    return render(request,'in2.html',context)

After success, in order to display the difference of the current page, you need to add an if in the for loop to determine whether i is the same as the current page. If they are the same, add a different style to the page.

for i in range(start_page, end_page + 1):
    if i == current_page:
        page_string + = f"<span style='background-color:#fff;'><a style='color:#000' href=?page={i}>{i}</a> </span>"
    else:
        page_string + = f"<span><a href=?page={i}>{i}</a></span>"

4. Data display

When adding data, please note that the last page of data is not full [44*8=352]. There are 350 pieces of data in total, so the end of the last page is the total number of data pieces.

#Get the starting position and ending position of the data [1,8],[9,16]
start = int(current_page - 1) * page_size + 1
if current_page == page_count:#When the current page is the last page, the data is not 8 pieces of data
        end = data_count
else:
        end = int(current_page) * page_size
print(start,end)

Supplement the start data and end data to the context dictionary. Integer numbers are used here to simulate the total number of data. In HTML, for cannot be used in the same way, and integer data cannot be iterated. Range(start,end, step) as an iterator

context={

“data”:range(start,end + 1),

}

Traverse data in HTML

<style>
.data{
      width: 300px;
      height: 166px;
      border: 1px solid #8a6d3b;
      margin-bottom: 30px;
}
</style>

<body>
<div class="data">
    {% for i in data %}
        <li>This is the {<!-- -->{ i }} piece of data</li>
    {% endfor %}
</div>
</body>

5. Previous page next page

When clicking on the page number, add a button for the previous page and the next page, and the last page number currently seen becomes the first page number.

I see that the previous page button is not displayed on the first page, and there is no button on the last page.

When the home page cannot be seen but does not exceed the plus or minus page, clicking on the previous page will pop up the appropriate page number. You should set page=1, pull back the jump position, and place the page to become a negative number. The same is true for the last page.

When the page number meets the requirement of adding or subtracting pages, the last page number will be changed to the first page number, and 2 times of plus will be added or subtracted from the page number of the current page.

# Previous page, next page
 if current_page <= plus + 1:#When the current page is in the first 5 pages, the previous page is not needed
     pre = ''
 else:
     if current_page <= plus * 2: #When the current page is on pages 5-10, click on the previous page to jump to page 1
         pre=f'<span class="updown"><a href=?page={1}>Homepage</a></span>'
     else:
         pre = f'<span class="updown"><a href=?page={current_page - plus * 2}>Previous page</a></span>'
 if current_page >= page_count - plus:
     next = ''
 else:
     if current_page >= page_count - plus * 2:
         next = f'<span class="updown"><a href=?page={page_count}>Last page</a></span>'
     else:
         next = f'<span class="updown"><a href=?page={current_page + plus * 2}>Next page</a></span>'

Integrate paging and page up and down programs to reduce if judgments

6. Database data paging

605/8=75, 605%8=5 [The last page is 75, there are 5 pieces of data] The first column is the id of the table, not the serial number, and there is a deleted id in the middle, so the final value is not 605

data_count = models.tablename.objects.all().count()

<div class="data">
    {% for i in data %}
        <li><span>{<!-- -->{ i.id }}</span> <span style="width: 130px">{<!-- -->{ i.phone }}</span > <span>{<!-- -->{ i.price }}</span></li>
    {% endfor %}
</div>

In SQL Server, the index starts counting from 1 and requires + 1, while the index of the MySql database starts from 0, so there is no need to add it. Pay attention to the difference in the starting index of the data you use.

7. Encapsulated paging

Create a software package named utils

Create SplitPage.py in utils, integrate the previous program, the package of the package, the method body of the method body, page_size defaults to 8 if not written, and loaded if written.

from django.utils.safestring import mark_safe
class Splitpagenumber:
    def __init__(self,request, queryset, page_size=8, plus=5, ):
        #Define variables, method body to implement paging
        if request.GET.get('page'):
            self.current_page = int(request.GET.get('page'))
        else:
            self.current_page = 1
        How many pages can ''' be divided into '''
        self.page_count,count = divmod(queryset.count(), page_size)
        if count:
            self.page_count + = 1

        start = int(self.current_page - 1) * page_size
        if self.current_page == self.page_count: # When the current page is the last page, the data is not 8 pieces of data
            end = queryset.count()
        else:
            end = int(self.current_page) * page_size

        self.data = queryset[start:end]
        self.plus =plus


    def html(self):
        #Realize the start page, end page, and previous page next page
        if self.current_page <= self.plus + 1:
            start_page = 1
            pre = ''
        else:
            start_page = self.current_page - self.plus
            if self.current_page <= self.plus * 2: # When the current page is on pages 5-10, click on the previous page to jump to page 1
                pre = f'<span class="updown"><a href=?page={1}>Homepage</a></span>'
            else:
                pre = f'<span class="updown"><a href=?page={self.current_page - self.plus * 2}>Previous page</a></span>'
        # If the current page is greater than or equal to the final page, the end page is always the end page; if the current page is less than the end page minus 5, the end page is the current page + 5
        if self.current_page >= self.page_count - self.plus:
            end_page = self.page_count
            next = ''
        else:
            end_page = self.current_page + self.plus
            if self.current_page >= self.page_count - self.plus * 2:
                next = f'<span class="updown"><a href=?page={self.page_count}>Last page</a></span>'
            else:
                next = f'<span class="updown"><a href=?page={self.current_page + self.plus * 2}>Next page</a></span>'
        """ Generate html format """
        page_string = ''
        page_string + = pre

        for i in range(start_page, end_page + 1):
            if i == self.current_page:
                page_string + = f"<span style='background-color:#fff;'><a style='color:#000' href=?page={i}>{i}</a> </span>"
            else:
                page_string + = f"<span><a href=?page={i}>{i}</a></span>"

        page_string + = next
        page_string = mark_safe("".join(page_string))

        return page_string

8. Use encapsulated paging

Complete the path link of in3, and then run in3

from app02.utils import SplitPage
def in3(request):
    queryset = models.User.objects.all()
    page_object = SplitPage.Splitpagenumber(request, queryset)
    context={
        "info":page_object.data,
        "page_string":page_object.html()
    }
    return render(request,'in3.html',context)

Default paging [add css for data display]

page_object = SplitPage.Splitpagenumber(request, queryset,page_size=31,plus=5)
page_object = SplitPage.Splitpagenumber(request, queryset,page_size=2,plus=10)

I only took a screenshot of the last page, and the paging display is different, but the data is the same.