Django框架完成读者浏览书籍,图书详情页,借阅管理

前情回顾:

使用Django框架实现简单的图书借阅系统——完成图书信息管理

文章目录

  • 1.完成展示图书信息功能
    • 1.1django 静态资源管理问题
    • 1.2编写图书展示模板HTML
  • 2.完成图书详情页功能
    • 2.1从后端获取图书详情信息
    • 2.2详情页面展示图书数据
  • 3.完成借阅管理功能
    • 3.1管理员管理借阅数据
      • 3.1.1完成用户功能,上传借阅信息
      • 3.1.2完成展示借阅数据功能
      • 3.1.3完成归还图书功能
      • 3.1.4完成删除借阅记录功能
  • 项目源码地址

1.完成展示图书信息功能

向读者展示所有图书数据,本质上和图书管理一样,向数据库查询图书数据,返回给前端,如果是前后端分离项目,可以合成一个API,但是这次项目没有用到前后端,所以要另外提供一个函数,返回给读者图书数据

def display_all_books(request):
    # 查询所有图书
    books = Book.objects.all()
    # 登录----- 展示-----HTML
    user_id = request.session.get('user_id')
    username = request.session.get('username')
    return render(request, 'reader/library_main.html', {'books': books, 'user_id': user_id, 'user_name': username})

与管理员稍有不同,展示读者页面的数据 ,不仅有图书数据,还有session,因为一会做借阅功能需要用户的ID,所以可以将用户的信息存放到session 传递给下一个页面

1.1django 静态资源管理问题

展示页面,用了 不少CSS和JS,如果说直接写在HTML页面,那显得太臃肿, 所以集成在外部css文件和JS文件,但是Django对这些静态资源支持的不是很好,如果我们想引用css文件不能直接引用,需要专门创建一个新的文件夹,并且告诉Django我们的静态资源在这个文件夹才可以,具体操作步骤如下:

  1. 首先在项目目录新建一个static文件夹
  2. 修改settings.py 告知Django static文件夹地址
STATIC_URL = '/static/'
# 静态文件的额外目录
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
    # 如果需要,添加更多目录
]
  1. 在HTML文件中,确保在需要使用静态文件的地方包含{% load static %}标签。
{% load static %}
<link rel="stylesheet" href="{% static 'myapp/css/style.css' %}">

1.2编写图书展示模板HTML

解决完静态资源文件问题,就可以编写HTML文件,这里用到了大量的css和js ,还用到了部分JQuery,在文章末尾会附上开源地址,大家可以去gitee下载源代码

{% load static %}
DOCTYPE html>
<html class="no-js" lang="zxx">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="meta description">
    <title>title>
    <meta name="referrer" content="no-referrer">
    

    {#    更改css 地址     {% static 'css/your_stylesheet.css' %}#}
    <link rel="shortcut icon" href="{% static 'assets/img/favicon.ico' %}" type="image/x-icon"/>

    
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i,700,900%7CYesteryear"
          rel="stylesheet">

    
    <link href="{% static 'assets/css/vendor.css' %}" rel="stylesheet">
    
    <link href="{% static 'assets/css/style.css' %}" rel="stylesheet">


head>

<body>


<header class="header-area">

    

    
    <div class="col-lg-3">
        <div class="header-configure-wrapper">
            <div class="header-configure-area">
                <ul class="nav justify-content-end">

                    <li class="user-hover">
                        <a href="#">
                            <i class="lnr lnr-user">i>
                        a>
                        <ul class="dropdown-list">
                            <li>
                                {% if user_name %}
                                    <a href="#" id="local_user_id">用户ID:{{ user_id}}a>
                                    <a href="#" id="user_name">当前用户:{{ user_name }}a>
                                {% else %}
                                    <a href="../login"  >请登录a>
                                {% endif %}
                            li>
                        ul>
                    li>

                ul>
            div>
        div>
    div>
    

header>



<aside class="off-canvas-wrapper">
    <div class="off-canvas-overlay">div>
    <div class="off-canvas-inner-content">
        <div class="btn-close-off-canvas">
            <i class="lnr lnr-cross">i>
        div>


    div>
    div>
aside>




<main>
    
    <div class="breadcrumb-area common-bg">
        <div class="container">
            <div class="row">
                <div class="col-12">
                    <div class="breadcrumb-wrap">
                        <nav aria-label="breadcrumb">
                            <h1 id="web_title">弄墨小轩h1>

                        nav>
                    div>
                div>
            div>
        div>
    div>
    

    
    <div class="shop-main-wrapper section-space pb-0">
        <div class="container">
            <div class="row">


                
                <div class="col-lg-9 order-1 order-lg-2">
                    <div class="shop-product-wrapper">
                        
                        <div class="shop-top-bar">
                            <div class="row align-items-center">
                                <div class="col-lg-7 col-md-6 order-2 order-md-1">
                                    <div class="top-bar-left">
                                        <div class="product-view-mode">
                                            <a class="active" href="#" data-target="grid-view" data-toggle="tooltip"
                                               title="Grid View"><i class="fa fa-th">i>a>
                                            <a href="#" data-target="list-view" data-toggle="tooltip" title="List View"><i
                                                    class="fa fa-list">i>a>
                                        div>

                                    div>
                                div>

                            div>
                        div>
                        

                        
                        <div class="shop-product-wrap grid-view row mbn-40" id="shopContainer">

                            {% for book in books %}
                                
                                <div class="col-md-4 col-sm-6">
                                    
                                    <div class="product-item">
                                        <figure class="product-thumb">
                                            <a href="/reader/{{ book.id }}/display">
                                                <img class="pri-img" src={{ book.image_link }} alt="product">
                                            a>
                                        figure>
                                        <div class="product-caption">
                                            <p class="product-name">
                                                <a href="/reader/{{ book.id }}/display">{{ book.title }}a>
                                            p>
                                            <div class="price-box">
                                                <span class="price-regular">{{ book.author }}span>
                                            div>
                                        div>
                                    div>
                                    
                                    
                                    <div class="product-list-item">
                                        <figure class="product-thumb">
                                            <a href="/reader/{{ book.id }}/display">
                                                <img class="pri-img" src={{ book.image_link }}  alt="product">
                                            a>
                                        figure>
                                        <div class="product-content-list">
                                            <h5 class="product-name"><a
                                                    href="/reader/{{ book.id }}/display">{{ book.title }}a>
                                            h5>
                                            <div class="price-box">
                                                <span class="price-regular">{{ book.title }}span>
                                            div>
                                            <p> 简介:{{ book.details }} p>
                                            <div class="button-group-list">
                                                <a class="btn-big" href="/reader/{{ book.id }}/display"
                                                   data-toggle="tooltip"
                                                   title="Add to Cart">
                                                    <i class="lnr lnr-cart">i>添加到书架
                                                a>
                                            div>
                                        div>
                                    div>

                                    
                                div>

                            {% endfor %}


                        div>
                        

                        
                        <div class="paginatoin-area text-center">
                            <input type="hidden" id="currentPage">
                            <input type="hidden" id="pageSize">
                            
                            <ul class="pagination-box" id="paginate">


                            ul>
                        div>
                        
                    div>
                div>
                
            div>
        div>
    div>
    
main>



<footer class="footer-wrapper">

    

    

    
    <div class="footer-bottom-area">
        <div class="container">
            <div class="row align-items-center">
                <div class="col-md-6 order-2 order-md-1">
                    <div class="copyright-text">
                        <p>Copyright © 2019.Company name All rights reserved.<a target="_blank"
                                                                                     href="http://sc.chinaz.com/moban/">a>
                        p>
                    div>
                div>
                <div class="col-md-6 order-1 order-md-2">
                    <div class="footer-social-link">
                        <a href="#"><i class="fa fa-twitter">i>a>
                        <a href="#"><i class="fa fa-facebook">i>a>
                        <a href="#"><i class="fa fa-linkedin">i>a>
                        <a href="#"><i class="fa fa-instagram">i>a>
                    div>
                div>
            div>
        div>
    div>
    

footer>



<div class="modal" id="quick_view">
    <div class="modal-dialog modal-lg modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">×button>
            div>
            <div class="modal-body">
                
                <div class="product-details-inner">
                    <div class="row">
                        <div class="col-lg-5 col-md-5">
                            <div class="product-large-slider">
                                <div class="pro-large-img">
                                    <img src="assets/img/product/product-details-img1.jpg" alt="product-details"/>
                                div>
                                <div class="pro-large-img">
                                    <img src="assets/img/product/product-details-img2.jpg" alt="product-details"/>
                                div>
                                <div class="pro-large-img">
                                    <img src="assets/img/product/product-details-img3.jpg" alt="product-details"/>
                                div>
                                <div class="pro-large-img">
                                    <img src="assets/img/product/product-details-img4.jpg" alt="product-details"/>
                                div>
                            div>
                            <div class="pro-nav slick-row-10 slick-arrow-style">
                                <div class="pro-nav-thumb">
                                    <img src="assets/img/product/product-details-img1.jpg" alt="product-details"/>
                                div>
                                <div class="pro-nav-thumb">
                                    <img src="assets/img/product/product-details-img2.jpg" alt="product-details"/>
                                div>
                                <div class="pro-nav-thumb">
                                    <img src="assets/img/product/product-details-img3.jpg" alt="product-details"/>
                                div>
                                <div class="pro-nav-thumb">
                                    <img src="{% static 'assets/img/product/product-details-img4.jpg" alt="product-details' %}"/>
                                div>
                            div>
                        div>
                        <div class="col-lg-7 col-md-7">
                            <div class="product-details-des quick-details">
                                <h3 class="product-name">Orchid flower white stickh3>
                                <div class="ratings d-flex">
                                    <span><i class="lnr lnr-star">i>span>
                                    <span><i class="lnr lnr-star">i>span>
                                    <span><i class="lnr lnr-star">i>span>
                                    <span><i class="lnr lnr-star">i>span>
                                    <span><i class="lnr lnr-star">i>span>
                                    <div class="pro-review">
                                        <span>1 Reviewsspan>
                                    div>
                                div>
                                <div class="price-box">
                                    <span class="price-regular">$70.00span>
                                    <span class="price-old"><del>$90.00del>span>
                                div>
                                <h5 class="offer-text"><strong>Hurry upstrong>! offer ends in:h5>
                                <div class="product-countdown" data-countdown="2019/08/25">div>
                                <div class="availability">
                                    <i class="fa fa-check-circle">i>
                                    <span>200 in stockspan>
                                div>
                                <p class="pro-desc">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
                                    nonumy
                                    eirmod tempor invidunt ut labore et dolore magna aliquyam erat.p>
                                <div class="quantity-cart-box d-flex align-items-center">
                                    <h5>qty:h5>
                                    <div class="quantity">
                                        <div class="pro-qty"><input type="text" value="1">div>
                                    div>
                                    <div class="action_link">
                                        <a class="btn btn-cart2" href="#">Add to carta>
                                    div>
                                div>
                                <div class="useful-links">
                                    <a href="#" data-toggle="tooltip" title="Compare"><i
                                            class="lnr lnr-sync">i>comparea>
                                    <a href="#" data-toggle="tooltip" title="Wishlist"><i
                                            class="lnr lnr-heart">i>wishlista>
                                div>
                                <div class="like-icon">
                                    <a class="facebook" href="#"><i class="fa fa-facebook">i>likea>
                                    <a class="twitter" href="#"><i class="fa fa-twitter">i>tweeta>
                                    <a class="pinterest" href="#"><i class="fa fa-pinterest">i>savea>
                                    <a class="google" href="#"><i class="fa fa-google-plus">i>sharea>
                                div>
                            div>
                        div>
                    div>
                div> 
            div>
        div>
    div>
div>



<div class="offcanvas-search-wrapper">
    <div class="offcanvas-search-inner">
        <div class="offcanvas-close">
            <i class="lnr lnr-cross">i>
        div>
        <div class="container">
            <div class="offcanvas-search-box">
                <form class="d-flex bdr-bottom w-100">
                    <input type="text" placeholder="输入鲜花名字" id="search_input">
                    <button class="search-btn"><i class="lnr lnr-magnifier">i>searchbutton>
                form>
            div>
        div>
    div>
div>



<div class="scroll-top not-visible">
    <i class="fa fa-angle-up">i>
div>





<script src="{% static 'assets/js/vendor.js' %}">script>

<script src="{% static 'assets/js/active.js' %}">script>

<script src="{% static 'assets/js/jquery.min.js ' %}">script>


<script>
        // 当文档加载完成后执行
        $(document).ready(function() {
            //直接从获取Django渲染的值
            // 存储值到localStorage
            localStorage.setItem('user_id', {{user_id}});
        });
script>

body>

html>

其中我们后端已经传了用户的ID,可以在js中直接取到值,一会这个值,需要从展示页面传递到详情页,后端之间可以用session传值,涉及到页面之间的传值可以用localStorage来传递,展示页面存储用户ID, 详情页取出用户ID,确保加入书架的时候有用户ID。

<script>
        // 当文档加载完成后执行
        $(document).ready(function() {
            //直接从获取Django渲染的值
            // 存储值到localStorage
            localStorage.setItem('user_id', {{user_id}});
        });
script>

效果如下:支持两种展示方式
Django框架完成读者浏览书籍,图书详情页,借阅管理_第1张图片
Django框架完成读者浏览书籍,图书详情页,借阅管理_第2张图片
并且点击标题或者图片可以跳转到详情页。

2.完成图书详情页功能

2.1从后端获取图书详情信息

在图书展示页面,点击图片或者标题,将ID传递给后端,后端根据ID查询图书信息,返回给详情页面。

def display_book_by_id(request, id):
    # 根据ID查询book
    book = Book.objects.filter(id=id).first()
    return render(request, 'reader/book.html', {'book': book})

2.2详情页面展示图书数据

{% load static %}
<Html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="meta description">
    <title>title>

    
    <link rel="shortcut icon" href="assets/img/favicon.ico" type="image/x-icon"/>

    
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i,700,900%7CYesteryear"
          rel="stylesheet">

    
    <link href="{% static 'assets/css/vendor.css' %}" rel="stylesheet">
    
    <link href="{% static 'assets/css/style.css' %}" rel="stylesheet">

    

head>

<body>


<header class="header-area">
    
    <div class="main-header d-none d-lg-block">
        
        <div class="header-main-area sticky">
            <div class="container">
                <div class="row align-items-center position-relative">

                    
                    <div class="col-lg-3">
                        <div class="logo">
                            <a href="index.jsp">
                                <img src="assets/img/logo/headset.png" alt="">
                            a>
                        div>
                    div>

                    
                    <div class="col-lg-6 position-static">
                        <div class="main-menu-area">
                            <div class="main-menu">
                                
                                <nav class="desktop-menu">
                                    <ul>
                                        
                                        <li><a href="/display_book">弄轩小墨a>li>

                                    ul>
                                nav>
                                
                            div>
                        div>
                    div>
                    

                    
                    <div class="col-lg-3">
                        <div class="header-configure-wrapper">
                            <div class="header-configure-area">
                                <ul class="nav justify-content-end">
                                    <li class="user-hover">
                                        <a href="#">
                                            <i class="lnr lnr-user">i>
                                        a>
                                        <ul class="dropdown-list">
                                            <li><label id="user_id_display">label>li>
                                        ul>
                                    li>
                                ul>
                            div>
                        div>
                    div>
                    

                div>
            div>
        div>
        
    div>
    


header>



<aside class="off-canvas-wrapper">
    <div class="off-canvas-overlay">div>
    <div class="off-canvas-inner-content">
        <div class="btn-close-off-canvas">
            <i class="lnr lnr-cross">i>
        div>

        <div class="off-canvas-inner">
            
            <div class="search-box-offcanvas">
                <form>
                    <input type="text" placeholder="Search Here...">
                    <button class="search-btn"><i class="lnr lnr-magnifier">i>button>
                form>
            div>
            

            
            <div class="mobile-navigation">

                
                <nav>
                    <ul class="mobile-menu">
                        <li><a href="index.jsp">Homea>li>
                        <li><a href="library_main.html">Shopa>li>
                        <li><a href="product-details.jsp">Product Detailsa>li>
                    ul>
                nav>
                
            div>
            

            <div class="mobile-settings">
                <ul class="nav">
                    <li>
                        <div class="dropdown mobile-top-dropdown">
                            <a href="#" class="dropdown-toggle" id="currency" data-toggle="dropdown"
                               aria-haspopup="true" aria-expanded="false">
                                Currency
                                <i class="fa fa-angle-down">i>
                            a>
                            <div class="dropdown-menu" aria-labelledby="currency">
                                <a class="dropdown-item" href="#">$ USDa>
                                <a class="dropdown-item" href="#">$ EUROa>
                            div>
                        div>
                    li>
                    <li>
                        <div class="dropdown mobile-top-dropdown">
                            <a href="#" class="dropdown-toggle" id="myaccount" data-toggle="dropdown"
                               aria-haspopup="true" aria-expanded="false">
                                My Account
                                <i class="fa fa-angle-down">i>
                            a>
                            <div class="dropdown-menu" aria-labelledby="myaccount">
                                <a class="dropdown-item" href="#">my accounta>
                                <a class="dropdown-item" href="#"> logina>
                                <a class="dropdown-item" href="#">registera>
                            div>
                        div>
                    li>
                ul>
            div>

            
            <div class="offcanvas-widget-area">
                <div class="off-canvas-contact-widget">
                    <ul>
                        <li><i class="fa fa-mobile">i>
                            <a href="#">0123456789a>
                        li>
                        <li><i class="fa fa-envelope-o">i>
                            <a href="#">[email protected]a>
                        li>
                    ul>
                div>
                <div class="off-canvas-social-widget">
                    <a href="#"><i class="fa fa-facebook">i>a>
                    <a href="#"><i class="fa fa-twitter">i>a>
                    <a href="#"><i class="fa fa-pinterest-p">i>a>
                    <a href="#"><i class="fa fa-linkedin">i>a>
                    <a href="#"><i class="fa fa-youtube-play">i>a>
                div>
            div>
            
        div>
    div>
aside>




<main id="app">
    
    <div class="breadcrumb-area common-bg">
        <div class="container">
            <div class="row">
                <div class="col-12">
                    <div class="breadcrumb-wrap">
                        <nav aria-label="breadcrumb">
                            <h1>h1>
                            <ul class="breadcrumb">
                                <li class="breadcrumb-item"><a href="/display_book/"><i class="fa fa-home">i>a>li>
                                <li class="breadcrumb-item active" aria-current="page">{{ book.title }}li>
                            ul>
                        nav>
                    div>
                div>
            div>
        div>
    div>
    

    
    <div class="shop-main-wrapper section-space">
        <div class="container">
            <div class="row">
                
                <div class="col-lg-12 order-1 order-lg-2">
                    
                    <div class="product-details-inner">
                        <div class="row">
                            <div class="col-lg-5">
                                <div class="product-large-slider">
                                    <div class="pro-large-img img-zoom">
                                        <img src="{{ book.image_link }}" alt="product-details"/>
                                    div>

                                div>

                            div>
                            <div class="col-lg-7">
                                <div class="product-details-des">
                                    <h3 class="product-name">{{ book.title }}h3>
                                    <input id="id" type="hidden" value={{ book.id }}>
                                    <div class="ratings d-flex">
                                        <span><i class="lnr lnr-star">i>span>
                                        <span><i class="lnr lnr-star">i>span>
                                        <span><i class="lnr lnr-star">i>span>
                                        <span><i class="lnr lnr-star">i>span>
                                        <span><i class="lnr lnr-star">i>span>
                                    div>
                                    <div class="price-box">
                                        <span class="price-regular">{{ book.author }}span>

                                    div>

                                    <p class="pro-desc">简介:{{ book.details }}p>

                                    <div class="quantity-cart-box d-flex align-items-center">

                                        <div class="action_link">
                                            {#                                           请求后台方法#}
                                            <a class="btn btn-cart2">加入到书架a>
                                            {% csrf_token %}
                                        div>
                                    div>
                                div>
                            div>
                        div>
                    div>
                    


                div>
                
            div>
        div>
    div>
    


main>




<div class="scroll-top not-visible">
    <i class="fa fa-angle-up">i>
div>



<script src="{% static 'assets/js/vendor.js' %}">script>

<script src="{% static 'assets/js/active.js' %}">script>
<script src="{% static 'assets/js/jquery.min.js' %}">script>

<script>
    // 当文档加载完成后执行
    $(document).ready(function () {
        //直接从获取Django渲染的值
        // 存储值到localStorage
        var storedValue = localStorage.getItem('user_id');
        // 检查值是否存在
        if (storedValue !== null) {
            $('#user_id_display').text('User ID: ' + storedValue);
        }
        $(".btn-cart2").on("click", function () {
            // 在这里执行点击事件触发的操作

            //判断是否有ID值 没有的话跳转到登录页面

            if (storedValue == null) {
                alert("请先登录")
                window.location.href = "/login";
            } else {
                // 构建要发送的数据
                var data = {
                    bookId: {{book.id}},  // 替换为实际的书籍ID
                    user_id: storedValue
                };
                // 获取 CSRF token
                var csrfToken = document.querySelector('input[name="csrfmiddlewaretoken"]').value;
                console.log('CSRF Token:', csrfToken);
                console.log('data Token:', JSON.stringify(data));
                // 发起POST请求
                fetch('/borrow_book/', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRFToken': csrfToken,  // 添加 CSRF token

                    },
                    body: JSON.stringify(data),
                })
                    .then(response => {
                        // 处理响应
                        if (!response.ok) {
                            throw new Error('Network response was not ok');
                        }
                        return response.json();  // 如果服务器返回JSON,解析响应
                    })
                    .then(data => {
                        // 处理返回的数据
                        alert('添加成功')
                    })
                    .catch(error => {
                        // 处理错误
                        console.error('There has been a problem with your fetch operation:', error);
                    });
            }
        });
    });
script>
body>
Html>


敲黑板,这里有一个重点,留到借阅管理讲
详情页效果:
Django框架完成读者浏览书籍,图书详情页,借阅管理_第3张图片

3.完成借阅管理功能

3.1管理员管理借阅数据

首先需要创建借阅管理模型

class BorrowRecord(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='borrow_records')
    book_id = models.IntegerField()
    returned = models.BooleanField(default=False)
    borrow_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.user.username} borrowed book with ID {self.book_id} on {self.borrow_time}"

    class Meta:
        ordering = ['-borrow_time']

这里添加了四个字段:用户ID,并且作为借阅表的外键,绑定用户表的ID,实际开发一般不用外键,这里简单探讨Django的模型功能。图书ID,是否归还字段,借阅时间,由Django自动插入当前时间。
创建好模型,交给Django创建数据表即可。在终端中输入迁移命令

python manage.py migrate
python manage.py makemigrations bookModel  # 让 Django 知道我们在我们的模型有一些变更
python manage.py migrate bookModel   # 创建表结构

3.1.1完成用户功能,上传借阅信息

def borrow_book(request):
    if request.method == 'POST':
        try:
            # 从请求的 body 中获取 JSON 数据
            data = json.loads(request.body.decode('utf-8'))
            print(data)
            # 获取 user_id 和 book_id
            user_id = data.get('user_id')
            book_id = data.get('bookId')
            # 确保 user_id 和 book_id 非空
            if user_id is not None and book_id is not None:
                # 获取用户和图书对象
                user = get_object_or_404(User, id=user_id)
                # 假设 Book 模型表示图书,你可以根据实际情况修改
                # book = get_object_or_404(Book, id=book_id)
                # 创建借阅记录
                BorrowRecord.objects.create(user=user, book_id=book_id)
                # 返回成功的 JSON 响应
                return JsonResponse({'status': 'success'})

            else:
                # 返回错误的 JSON 响应,表示缺少必要的数据
                return JsonResponse({'status': 'error', 'message': '缺少用户ID或者图书ID'}, status=400)

        except json.JSONDecodeError:
            # 返回错误的 JSON 响应,表示无法解析 JSON 数据
            return JsonResponse({'status': 'error', 'message': '无效的JSon数据'}, status=400)

    else:
        # 返回错误的 JSON 响应,表示不支持的请求方法
        return JsonResponse({'status': 'error', 'message': 'Method not allowed'}, status=405)

重点:我们是在详情页面,点击加入书架的时候,完成信息的上传。一般思路使用Form表单进行POST请求,这里使用的JQuery的fetch 来完成POST请求

<script>
    // 当文档加载完成后执行
    $(document).ready(function () {
        //直接从获取Django渲染的值
        // 存储值到localStorage
        var storedValue = localStorage.getItem('user_id');
        // 检查值是否存在
        if (storedValue !== null) {
            $('#user_id_display').text('User ID: ' + storedValue);
        }
        $(".btn-cart2").on("click", function () {
            // 在这里执行点击事件触发的操作
            //判断是否有ID值 没有的话跳转到登录页面
            if (storedValue == null) {
                alert("请先登录")
                window.location.href = "/login";
            } else {
                // 构建要发送的数据
                var data = {
                    bookId: {{book.id}},  // 替换为实际的书籍ID
                    user_id: storedValue
                };
                // 获取 CSRF token
                var csrfToken = document.querySelector('input[name="csrfmiddlewaretoken"]').value;
                console.log('CSRF Token:', csrfToken);
                console.log('data Token:', JSON.stringify(data));
                // 发起POST请求
                fetch('/borrow_book/', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'X-CSRFToken': csrfToken,  // 添加 CSRF token
                    },
                    body: JSON.stringify(data),
                })
                    .then(response => {
                        // 处理响应
                        if (!response.ok) {
                            throw new Error('Network response was not ok');
                        }
                        return response.json();  // 如果服务器返回JSON,解析响应
                    })
                    .then(data => {
                        // 处理返回的数据
                        alert('添加成功')
                    })
                    .catch(error => {
                        // 处理错误
                        console.error('There has been a problem with your fetch operation:', error);
                    });
            }
        });
    });
script>

上传之前,先判断有没有用户ID。之前在展示页面已经存储了用户ID,在详情页面取出ID即可,如果发现没有ID,则跳转到登录页面,让用户完成登录之后,再上传数据。
另外POST请求一定要有csrfToken ,在HTML页面加入 {% csrf_token %} 之后,Django会给我们生成csrfToken。利用JQuery提取Token的值,完成POST请求。

3.1.2完成展示借阅数据功能

与用户管理,图书管理,套路一样,这里不过多阐述

def get_all_records(request):
    # 查询所有记录
    records = BorrowRecord.objects.all()
    return render(request, 'borrow_list.html', {'records': records})

页面进行展示

DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>管理菜单title>
    <style>
        /* 菜单样式 */
        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
        }

        .sidebar {
            width: 250px;
            background-color: #333;
            height: 100%;
            position: fixed;
            left: 0;
            top: 0;
            overflow-x: hidden;
        {#padding-top: 20px;#}
        }

        .sidebar a {
            padding: 10px 16px;
            margin: 20px;
            text-decoration: none;
            font-size: 22px;
            color: #85f112;
            display: block;
            transition: 0.3s;

        }

        .sidebar a:hover {
            background-color: #0edcac;
            color: black;
        }

        .content {
            margin-left: 250px;
            padding: 20px;
        }

        .header {
            background-color: #f1f1f1;
            padding: 10px;
            text-align: center;
        }

        {#    美化表格#}
        table {
            border-collapse: collapse;
            width: 100%;
        }

        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }

        th {
            background-color: #f2f2f2;
        }

        tr:nth-child(even) {
            background-color: #f9f9f9;
        }

    style>
head>
<body>

<div class="sidebar">
    <div class="header">
        <h2>管理菜单h2>
    div>
    <a href="../user_list/">用户管理a>
    <a href="../book_list/">图书管理a>
    <a href="../borrow_list/">借阅管理a>
    <a href="../migrations_list/">迁移记录a>
div>

<div class="content">
    
    <h2>用户列表h2>
    <table>
        <tr>
            <th>编号th>
            <th>图书IDth>
            <th>用户IDth>
            <th>是否归还th>
            <th>借阅时间th>
            <th>操作th>
            
        tr>
        {% for record in records %}
            <tr>
                <td>{{ record.id }}td>
                <td>{{ record.book_id }}td>
                <td>{{ record.user_id }}td>
                <td>    {% if record.returned == 0 %}
                    未归还
                {% elif record.returned == 1 %}
                    归还
                {% else %}
                    Unknown
                {% endif %}td>
                <td>{{ record.borrow_time }}td>
                <td>
                    <a href="/book/{{  record.id  }}/returned/">归还a> | <a href="/delete_record/{{   record.id }}/">删除a>
                td>
                
            tr>
        {% endfor %}
    table>
div>

body>
html>

效果如图:
Django框架完成读者浏览书籍,图书详情页,借阅管理_第4张图片

3.1.3完成归还图书功能

这里也可以做成读者功能,这里简化了功能,只做了管理员功能,感兴趣的伙伴,可以下载源码,进行二次开发

def update_borrow_record(request, record_id):
    borrow_record = get_object_or_404(BorrowRecord, id=record_id)
    # 取反
    borrow_record.returned = not borrow_record.returned
    borrow_record.save()
    return redirect('/borrow_list')

3.1.4完成删除借阅记录功能

def delete_book(request, id):
    try:
        print(id)
        record = BorrowRecord.objects.filter(id=id).first()
        print(record)
        record.delete()
        return redirect('/borrow_list')
        # 重定向到用借阅页面
    except BorrowRecord.DoesNotExist:
        return HttpResponse('记录不存在')

最后附上开源地址

项目源码地址

链接: Django 图书借阅系统

你可能感兴趣的:(Django学习,django,python,后端)