Django-开发一个列表页面

需求

  1. 基于ListView,创建一个列表视图,用于展示"BookInfo"表的信息
  2. 要求提供分页
  3. 提供对书名,作者,描述的查询功能

示例展示:
在这里插入图片描述

1. 数据模型

models.py

class BookInfo(models.Model):
    title=models.CharField(verbose_name="书名",max_length=100)
    author=models.CharField(verbose_name="作者",max_length=100)
    desc=models.TextField(verbose_name="介绍")
    create_at=models.DateTimeField(verbose_name="创建时间",auto_now=True)
    update_at=models.DateTimeField(verbose_name="更新时间",auto_now_add=True)

2. 视图

views.py

from functools import reduce
from typing import Any
from django.shortcuts import render,redirect  
from django.db.models import Q
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from .models import *
from .forms import *

class BookListView(ListView):
    model=BookInfo
    template_name = "demo1/book_list.html"
    paginate_by = 10
    def get_queryset(self):
        title = self.request.GET.get('title')
        author = self.request.GET.get('author')
        content = self.request.GET.get('content')
        # 如果有任意参数不为空,则构建Q对象进行查询
        queries = [Q(titile__icontains=title) if title else Q(),
                   Q(author__icontains=author) if author else Q(),
                   Q(desc__icontains=content) if content else Q()]
        # 使用Q对象的&操作符组合查询条件
        queryset = BookInfo.objects.filter(reduce(lambda x, y: x & y, queries)) if queries else BookInfo.objects.all()

        return queryset


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # 保留查询参数到分页链接
        query_params = self.request.GET.copy()
        if 'page' in query_params:
            del query_params['page']  # 移除现有的页码参数以避免冲突

        paginator = context['paginator']
        page_numbers_range = 5  # 您可以根据需要调整显示的页码范围大小
        max_index = len(paginator.page_range)

        page = self.request.GET.get('page')
        current_page = int(page) if page else 1

        start_index = int((current_page - 1) / page_numbers_range) * page_numbers_range
        end_index = start_index + page_numbers_range
        if end_index >= max_index:
            end_index = max_index

        page_range = paginator.page_range[start_index:end_index]
        context['page_range'] = page_range
        context['query_params'] = query_params.urlencode()  # 将查询参数编码为URL字符串

        return context

    def get(self, request, *args, **kwargs):
        # 如果是重定向回来的,需要处理paginate_by参数
        if 'paginate_by' in request.GET:
            try:
                paginate_by = int(request.GET['paginate_by'])
                if paginate_by > 0:  # 防止不合法的值
                    self.paginate_by = paginate_by
            except ValueError:
                pass  # 如果转换失败,忽略错误,使用默认设置

        return super().get(request, *args, **kwargs)

class BookDetailView(DetailView):
    model=BookInfo
    template_name = "demo1/book_detail.html"
    context_object_name = "book"

注册路由(urls.py)

from django.urls import path
from .views import *

urlpatterns = [
   path("book",BookListView.as_view(),name="book-list"),
   path("book/detail/<int:pk>/",BookDetailView.as_view(),name="book-detail"),
]

3. 页面代码

列表页:

{% extends 'layout.html' %}

{% block main %}
    <div class="panel panel-default">
        <div class="container">
            <form method="GET">
                检索:
                <input type="text" name="title" placeholder="书名" value="{{ request.GET.title }}">
                <input type="text" name="author" placeholder="作者" value="{{ request.GET.author }}">
                <input type="text" name="content" placeholder="内容关键字" value="{{ request.GET.content }}">
                <button type="submit">搜索</button>&nbsp; <a href="{% url 'book-list' %}" class="btn-sm btn-danger">清空查询条件</a>
            </form>
        </div>
        <hr>
        <div class="panel-body">
            <table class="table table-striped">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>书名</th>
                    <th>作者</th>
                    <th>说明</th>
                    <th>创建时间</th>
                    <th>更新时间</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>

                {% for book in object_list %}
                    <tr>
                        <td>{{ book.id }}</td>
                        <td>{{ book.titile }}</td>
                        <td>{{ book.author }}</td>
                        <td>{{ book.desc }}</td>
                        <td>{{ book.create_at }}</td>
                        <td>{{ book.update_at }}</td>
                        <td><a href="{% url 'book-detail' book.id %}">查看详情</a></td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>

            {% if is_paginated %}
                <div class="pagination">
                    <p>第 {{ page_obj.number }} 页 / 共 {{ page_obj.paginator.num_pages }} 页</p>
                    <!-- 首页 -->
                    {% if page_obj.has_previous %}
                        <a href="?{{ query_params }}&page=1">首页</a>
                    {% endif %}

                    <!-- 上一页 -->
                    {% if page_obj.has_previous %}
                        <a href="?{{ query_params }}&page={{ page_obj.previous_page_number }}">上一页</a>
                    {% endif %}



                    <!-- 中间页码,显示首末3页及当前页附近的页码,其余用省略号表示 -->
                    {% for num in page_obj.paginator.page_range %}
                        {% if num == page_obj.number %}
                            <span>{{ num }}</span> <!-- 当前页不做成链接 -->
                        {% elif num >= page_obj.number|add:-2 and num <= page_obj.number|add:2 %}
                            <a href="?{{ query_params }}&page={{ num }}">{{ num }}</a>
                        {% elif num in page_obj.paginator.page_range|slice:":3" or num in page_obj.paginator.page_range|slice:"-3:" %}
                            <a href="?{{ query_params }}&page={{ num }}">{{ num }}</a> <!-- 确保首末3页始终显示 -->
                        {% elif num == page_obj.number|add:-3 or num == page_obj.number|add:3 %}
                            <span>...</span>
                        {% endif %}
                    {% endfor %}
                    <!-- 下一页 -->
                    {% if page_obj.has_next %}
                        <a href="?{{ query_params }}&page={{ page_obj.next_page_number }}">下一页</a>
                    {% endif %}

                    <!-- 尾页 -->
                    {% if page_obj.has_next %}
                        <a href="?{{ query_params }}&page={{ page_obj.paginator.num_pages }}">尾页</a>
                    {% endif %}
                    <!-- 当前页及总页数信息 -->

                    <!-- 跳转到指定页的表单 -->
                    <label for="jumpToPage">跳转到页数:</label>
                    <input type="number" id="jumpToPage" min="1">
                    <button onclick="jumpToPage()">跳转</button>
                </div>
                </div>
            {% endif %}
    </div>

    <script>
        function jumpToPage() {
            var jumpTo = document.getElementById('jumpToPage').value;
            var currentQueryParams = new URLSearchParams(window.location.search);
            if (jumpTo.trim() !== '') { // 确保输入有效
                // 保留现有查询参数,并添加或更新'page'参数
                currentQueryParams.set('page', jumpTo);
                window.location.href = window.location.pathname + '?' + currentQueryParams.toString();
            } else {
                alert('请输入有效的页数');
            }
        }
    </script>
{% endblock %}

详情页(略)

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白日与明月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值