Django-开发一个列表页面

需求

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

示例展示:

1. 数据模型

models.py

python 复制代码
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

python 复制代码
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. 页面代码

列表页:

html 复制代码
{% 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 %}

详情页(略)

相关推荐
blues_C3 小时前
十三、【核心功能篇】测试计划管理:组织和编排测试用例
vue.js·django·测试用例·drf·测试平台
恸流失11 小时前
DJango项目
后端·python·django
编程大全20 小时前
41道Django高频题整理(附答案背诵版)
数据库·django·sqlite
网安小张1 天前
解锁FastAPI与MongoDB聚合管道的性能奥秘
数据库·python·django
KENYCHEN奉孝1 天前
Pandas和Django的示例Demo
python·django·pandas
老胖闲聊1 天前
Python Django完整教程与代码示例
数据库·python·django
noravinsc1 天前
django paramiko 跳转登录
后端·python·django
践行见远1 天前
django之请求处理过程分析
数据库·django·sqlite
声声codeGrandMaster1 天前
Django之表格上传
后端·python·django
菌菌的快乐生活1 天前
网站静态文件加速-Django项目静态文件存储到腾讯云COS存储提升网络请求速度
django·cos存储