赞
踩
前情回顾:
使用Django框架实现简单的图书借阅系统——完成图书信息管理
向读者展示所有图书数据,本质上和图书管理一样,向数据库查询图书数据,返回给前端,如果是前后端分离项目,可以合成一个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 传递给下一个页面
展示页面,用了 不少CSS和JS,如果说直接写在HTML页面,那显得太臃肿, 所以集成在外部css文件和JS文件,但是Django对这些静态资源支持的不是很好,如果我们想引用css文件不能直接引用,需要专门创建一个新的文件夹,并且告诉Django我们的静态资源在这个文件夹才可以,具体操作步骤如下:
STATIC_URL = '/static/'
# 静态文件的额外目录
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
# 如果需要,添加更多目录
]
{% load static %}
<link rel="stylesheet" href="{% static 'myapp/css/style.css' %}">
解决完静态资源文件问题,就可以编写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"> <!--=== Favicon ===--> {# 更改css 地址 {% static 'css/your_stylesheet.css' %}#} <link rel="shortcut icon" href="{% static 'assets/img/favicon.ico' %}" type="image/x-icon"/> <!-- Google fonts include --> <link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i,700,900%7CYesteryear" rel="stylesheet"> <!-- All Vendor & plugins CSS include --> <link href="{% static 'assets/css/vendor.css' %}" rel="stylesheet"> <!-- Main Style CSS {% static 'assets/css/style.css' %} --> <link href="{% static 'assets/css/style.css' %}" rel="stylesheet"> </head> <body> <!-- Start Header Area --> <header class="header-area"> <!-- main menu area end --> <!-- mini cart area start --> <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> <!-- mini cart area end --> </header> <!-- end Header Area --> <!-- off-canvas menu start --> <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> <!-- off-canvas menu end --> <!-- main wrapper start --> <main> <!-- breadcrumb area start --> <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> <!-- breadcrumb area end --> <!-- page main wrapper start --> <div class="shop-main-wrapper section-space pb-0"> <div class="container"> <div class="row"> <!-- shop main wrapper start --> <div class="col-lg-9 order-1 order-lg-2"> <div class="shop-product-wrapper"> <!-- shop product top wrap start --> <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> <!-- shop product top wrap start --> <!-- product item list wrapper start --> <div class="shop-product-wrap grid-view row mbn-40" id="shopContainer"> {% for book in books %} <!-- for 循环 解决--> <div class="col-md-4 col-sm-6"> <!-- product grid start --> <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> <!-- product grid end --> <!-- product list item begin --> <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> <!-- product list item end --> </div> {% endfor %} </div> <!-- product item list wrapper end --> <!-- start pagination area --> <div class="paginatoin-area text-center"> <input type="hidden" id="currentPage"> <input type="hidden" id="pageSize"> <!-- 绑定按钮事件 --> <ul class="pagination-box" id="paginate"> </ul> </div> <!-- end pagination area --> </div> </div> <!-- shop main wrapper end --> </div> </div> </div> <!-- page main wrapper end --> </main> <!-- main wrapper end --> <!-- Start Footer Area Wrapper --> <footer class="footer-wrapper"> <!-- footer widget area start --> <!-- footer widget area end --> <!-- footer bottom area start --> <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 bottom area end --> </footer> <!-- End Footer Area Wrapper --> <!-- Quick view modal start --> <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"> <!-- product details inner end --> <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 stick</h3> <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 Reviews</span> </div> </div> <div class="price-box"> <span class="price-regular">$70.00</span> <span class="price-old"><del>$90.00</del></span> </div> <h5 class="offer-text"><strong>Hurry up</strong>! 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 stock</span> </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 cart</a> </div> </div> <div class="useful-links"> <a href="#" data-toggle="tooltip" title="Compare"><i class="lnr lnr-sync"></i>compare</a> <a href="#" data-toggle="tooltip" title="Wishlist"><i class="lnr lnr-heart"></i>wishlist</a> </div> <div class="like-icon"> <a class="facebook" href="#"><i class="fa fa-facebook"></i>like</a> <a class="twitter" href="#"><i class="fa fa-twitter"></i>tweet</a> <a class="pinterest" href="#"><i class="fa fa-pinterest"></i>save</a> <a class="google" href="#"><i class="fa fa-google-plus"></i>share</a> </div> </div> </div> </div> </div> <!-- product details inner end --> </div> </div> </div> </div> <!-- Quick view modal end --> <!-- offcanvas search form start --> <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>search</button> </form> </div> </div> </div> </div> <!-- Scroll to top start --> <div class="scroll-top not-visible"> <i class="fa fa-angle-up"></i> </div> <!-- Scroll to Top End --> <!-- All vendor & plugins & active js include here --> <!--All Vendor Js --> <script src="{% static 'assets/js/vendor.js' %}"></script> <!-- Active Js --> <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>
效果如下:支持两种展示方式
并且点击标题或者图片可以跳转到详情页。
在图书展示页面,点击图片或者标题,将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})
{% 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> <!--=== Favicon ===--> <link rel="shortcut icon" href="assets/img/favicon.ico" type="image/x-icon"/> <!-- Google fonts include --> <link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i,700,900%7CYesteryear" rel="stylesheet"> <!-- All Vendor & plugins CSS include --> <link href="{% static 'assets/css/vendor.css' %}" rel="stylesheet"> <!-- Main Style CSS --> <link href="{% static 'assets/css/style.css' %}" rel="stylesheet"> <!--[if lt IE 9]> <script src="/oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="/oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <!-- Start Header Area --> <header class="header-area"> <!-- main header start --> <div class="main-header d-none d-lg-block"> <!-- header middle area start --> <div class="header-main-area sticky"> <div class="container"> <div class="row align-items-center position-relative"> <!-- start logo area --> <div class="col-lg-3"> <div class="logo"> <a href="index.jsp"> <img src="assets/img/logo/headset.png" alt=""> </a> </div> </div> <!-- main menu area start --> <div class="col-lg-6 position-static"> <div class="main-menu-area"> <div class="main-menu"> <!-- main menu navbar start --> <nav class="desktop-menu"> <ul> <!-- 跳转到首页 --> <li><a href="/display_book">弄轩小墨</a></li> </ul> </nav> <!-- main menu navbar end --> </div> </div> </div> <!-- main menu area end --> <!-- mini cart area start --> <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> <!-- mini cart area end --> </div> </div> </div> <!-- header middle area end --> </div> <!-- main header start --> </header> <!-- end Header Area --> <!-- off-canvas menu start --> <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"> <!-- search box start --> <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> <!-- search box end --> <!-- mobile menu start --> <div class="mobile-navigation"> <!-- mobile menu navigation start --> <nav> <ul class="mobile-menu"> <li><a href="index.jsp">Home</a></li> <li><a href="library_main.html">Shop</a></li> <li><a href="product-details.jsp">Product Details</a></li> </ul> </nav> <!-- mobile menu navigation end --> </div> <!-- mobile menu end --> <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="#">$ USD</a> <a class="dropdown-item" href="#">$ EURO</a> </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 account</a> <a class="dropdown-item" href="#"> login</a> <a class="dropdown-item" href="#">register</a> </div> </div> </li> </ul> </div> <!-- offcanvas widget area start --> <div class="offcanvas-widget-area"> <div class="off-canvas-contact-widget"> <ul> <li><i class="fa fa-mobile"></i> <a href="#">0123456789</a> </li> <li><i class="fa fa-envelope-o"></i> <a href="#">info@yourdomain.com</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> <!-- offcanvas widget area end --> </div> </div> </aside> <!-- off-canvas menu end --> <!-- main wrapper start --> <main id="app"> <!-- breadcrumb area start --> <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> <!-- breadcrumb area end --> <!-- page main wrapper start --> <div class="shop-main-wrapper section-space"> <div class="container"> <div class="row"> <!-- product details wrapper start --> <div class="col-lg-12 order-1 order-lg-2"> <!-- product details inner end --> <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> <!-- product details inner end --> </div> <!-- product details wrapper end --> </div> </div> </div> <!-- page main wrapper end --> </main> <!-- main wrapper end --> <!-- Scroll to top start --> <div class="scroll-top not-visible"> <i class="fa fa-angle-up"></i> </div> <!-- Scroll to Top End --> <!-- All vendor & plugins & active js include here --> <!--All Vendor Js --> <script src="{% static 'assets/js/vendor.js' %}"></script> <!-- Active Js --> <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>
敲黑板,这里有一个重点,留到借阅管理讲
详情页效果:
首先需要创建借阅管理模型
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 # 创建表结构
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请求。
与用户管理,图书管理,套路一样,这里不过多阐述
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>图书ID</th> <th>用户ID</th> <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>
效果如图:
这里也可以做成读者功能,这里简化了功能,只做了管理员功能,感兴趣的伙伴,可以下载源码,进行二次开发
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')
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 图书借阅系统
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。