26.9 Django书籍管理练习

news2024/9/27 5:45:22

2024-08-03_092752

1. 搭建环境

1.1 创建数据库

Django本身不会自动创建数据库服务器或数据库实例, 这一步需要手动完成.
可以使用Navicat可视化工具或者命令行创建'library'数据库, 编码格式为utf8_mp4.
# 连接数据库
mysql -h localhost -P 3306 -u root -p123456

# 创建library数据库并设置编码
create database library character set utf8mb4;

# 查看MySQL的编码(utf8mb4)
show variables like 'character_set_database';

# 查看library数据库的编码(utf8mb4)
show create database library;

image-20240725135432937

1.2 创建Django项目

使用Pychamr工具创建Django项目.
项目名称: MyDjango .
应用名称: library .

image-20240725140020124

1.3 连接MySQL数据库

编辑Django的settings.py配置文件, 使用MySQL数据库, 配置信息如下:
# 数据库配置
DATABASES = {
    'default': {
        # 使用mysql数据库
        'ENGINE': 'django.db.backends.mysql',
        # ip地址
        'HOST': '127.0.0.1',
        # 端口号
        'POST': 3306,
        # 登入用户
        'USER': 'root',
        # 登入密码
        'PASSWORD': '123456',
        # 连接的库
        'NAME': 'library',
        # 设置编码
        'CHARSET': 'utf8mb4'
    }
}

image-20240725140557401

1.4 创建表模型

* 1. 作者表(主表)一对一作者详情表(次表), 外键建立在作者详情表中名为author.
* 2. 出版社()一对多书籍表(), 外键字段建立在多的一方书籍表中名为publish.
* 3. 作者表多对多书籍表, 外键字段建立在查询频率高的一方书籍表中名为author.
1.4.1 作者表
作者表拥有id, name, age三个字段.
# library/models.py
from django.db import models


# 作者表模型
class Author(models.Model):
    # id字段(自动添加)
    name = models.CharField(max_length=12, verbose_name='作者名称')
    age = models.IntegerField(verbose_name='作者年龄')

    def __str__(self):
        return f'{self.name}'
    

image-20240725185152671

1.4.2 作者详情表
作者详情表拥有id, phone, addr, author_id四个字段.
# 作者详情表模型
class AuthorDetail(models.Model):
    # id字段(自动添加)
    phone = models.CharField(max_length=11, verbose_name='手机号码')
    addr = models.CharField(max_length=32, verbose_name='作者住址')
    # 外键字段(一对一关联作者表实例, 并设置级联删除)
    author = models.OneToOneField(to='Author', on_delete=models.CASCADE,
                                  related_name='author_detail', verbose_name='作者名称')

    def __str__(self):
        return f'{self.id}'

image-20240725185232084

1.4.3 出版社表
出版社表拥有id, name, email, 三个字段.
# 出版社表模型
class Publish(models.Model):
    # id字段(自动添加)
    name = models.CharField(max_length=12, verbose_name='出版社名称')
    addr = models.CharField(max_length=32, verbose_name='出版社地址')
    email = models.EmailField(verbose_name='出版社邮箱')

    def __str__(self):
        return f'{self.name}'

image-20240725185255202

1.4.4 书籍表模型
书籍表表拥有id, title, price, publication_date, publish, author六个字段.
# 书籍表模型
class Book(models.Model):
    # id字段(自动添加)
    title = models.CharField(max_length=32, verbose_name='书籍名称')
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='书籍价格')
    publication_date = models.DateField(auto_now_add=True, verbose_name='书籍发布日期')
    # 外键字段
    # 一对多出版社
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, verbose_name='出版社名称')
    # 多对多作者表
    author = models.ManyToManyField(to=Author, verbose_name='作者列表')

    def __str__(self):
        return f'{self.title}'

image-20240725185359669

书籍作者关联表会自动创建有id. book_id, author_id三个字段.
1.4.5 完整代码
from django.db import models


# 作者表模型
class Author(models.Model):
    # id字段(自动添加)
    name = models.CharField(max_length=12, verbose_name='作者名称')
    age = models.IntegerField(verbose_name='作者年龄')

    def __str__(self):
        return f'{self.name}'


# 作者详情表模型
class AuthorDetail(models.Model):
    # id字段(自动添加)
    phone = models.CharField(max_length=11, verbose_name='手机号码')
    addr = models.CharField(max_length=32, verbose_name='作者住址')
    # 外键字段(一对一关联作者表实例, 并设置级联删除)
    author = models.OneToOneField(to='Author', on_delete=models.CASCADE,
                                  related_name='author_detail', verbose_name='作者名称')

    def __str__(self):
        return f'{self.id}'


# 出版社表模型
class Publish(models.Model):
    # id字段(自动添加)
    name = models.CharField(max_length=12, verbose_name='出版社名称')
    addr = models.CharField(max_length=32, verbose_name='出版社地址')
    email = models.EmailField(verbose_name='出版社邮箱')

    def __str__(self):
        return f'{self.name}'


# 书籍表模型
class Book(models.Model):
    # id字段(自动添加)
    title = models.CharField(max_length=32, verbose_name='书籍名称')
    price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='书籍价格')
    publication_date = models.DateField(auto_now_add=True, verbose_name='书籍发布日期')
    # 外键字段
    # 一对多出版社
    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, verbose_name='出版社名称')
    # 多对多作者表
    author = models.ManyToManyField(to=Author, verbose_name='作者列表')

    def __str__(self):
        return f'{self.title}'

1.4.6 数据库迁移
# 在终端执行数据库迁移命令
PS D:\MyDjango> python manage.py makemigrations 
Migrations for 'library':
  library\migrations\0001_initial.py
    - Create model Author
    - Create model Publish
    - Create model Book
    - Create model AuthorDetail
    # 不知道为什么这里没有添加外键的提示???
PS D:\MyDjango> python manage.py migrate
...

image-20240725184054690

使用Navicat工具查询创建的表格.

image-20240725185843200

逆向数据库到模型.

image-20240725185754786

1.5 创建表记录

在Django ORM中, 执行数据库操作时, 通常不会直接返回一个'成功'的消息, 而是通过返回的结果或是否抛出异常来判断操作是否成功.
1.5.1 作者表记录
idnameage
1aa18
2bb19
3cc20
import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "MyDjango.settings")
    import django

    django.setup()

    from library.models import Author

    # 创建作者列表
    author_list = [
        Author(name='aa', age=18),
        Author(name='bb', age=19),
        Author(name='cc', age=20),
    ]

    # 批量创建作者实例
    res = Author.objects.bulk_create(author_list)
    print(res)

image-20240725211009120

image-20240726001916918

1.5.2 作者详情表记录
idphoneaddrauthor_id
1111北京1
2222上海2
3333深圳3
import os

if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyDjango.settings')
    import django

    django.setup()

    from library.models import AuthorDetail

    # 创建作者详情列表, 这里外键字段直接使用id值.
    author_detail_list = [
        AuthorDetail(phone='111', addr='北京', author_id=1),
        AuthorDetail(phone='222', addr='上海', author_id=2),
        AuthorDetail(phone='333', addr='深圳', author_id=3),
    ]

    # 批量创建作者详细实例
    res = AuthorDetail.objects.bulk_create(author_detail_list)
    print(res)

image-20240725202323335

image-20240726002115705

在Django中, bulk_create方法用于批量创建对象, 这样可以减少数据库操作次数, 提高性能.
但是, 使用bulk_create方法创建对象时, 这些对象在Python层面的实例并不会立即获得数据库中的ID.
这是因为bulk_create方法并不会立即对这些对象进行数据库查询以获取它们的ID.
1.5.3 出版社表记录
idnameaddremail
1北京出版社北京bj@qq.com
2上海出版社上海sh@qq.com
3深圳出版社深圳sz@qq.com
import os

if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyDjango.settings')
    import django

    django.setup()

    from library.models import Publish

    # 创建出版社实例列表
    publish_list = [
        Publish(name='北京出版社', addr='北京', email='bj@qq.com'),
        Publish(name='上海出版社', addr='上海', email='sh@qq.com'),
        Publish(name='深圳出版社', addr='深圳', email='sz@qq.com'),
    ]

    # 批量创建出版社实例
    res = Publish.objects.bulk_create(publish_list)
    print(res)

image-20240725211332466

image-20240726002010666

1.5.4 书籍表记录
idtitlepricepublication_datepublish_idauthor_id
1Python100.01自动生成1[1]
2MySQL200.02自动生成2[2]
3Linux300.03自动生成3[3]
4HTML400.04自动生成1[1 ,2]
import os

if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyDjango.settings')
    import django

    django.setup()

    from library.models import Book

    # 创建书籍实例列表
    book_list = [
        Book(title='Python', price=100.01, publish_id=1),
        Book(title='MySQL', price=200.02, publish_id=2),
        Book(title='Linux', price=300.03, publish_id=3),
        Book(title='HTML', price=400.04, publish_id=1)
    ]

    # 批量创建书籍实例
    res = Book.objects.bulk_create(book_list)
    print(res)

image-20240725224826292

image-20240726002053403

这里的对象不能使用外键, 例如:
book1 = Book(title='Python', price=100.01, publish_id=1)
book1.author.set([1])  # 视图在创建对象后使用外键设置多对多关联表的信息, 然后报错:
ValueError: "<Book: Python>" needs to have a value for field "id" before this many-to-many relationship can be used.
ValueError: "<Book: Python>" 需要先为字段 "id" 提供值, 然后才能使用此多对多关系.
这是因为Django的多对多关系是通过一个额外的表来实现的, 这个表需要存储关联的两个对象的主键.
如果一个对象还没有保存到数据库, 它就没有主键, 因此无法建立多对多关系.
1.5.5 书籍作者关联表
idbook_idauthor_id
111
222
333
441
542
在Django中, 当使用ManyToManyField字段时, Django会自动创建一个中间表来管理多对多关系.
然而, 这个中间表并没有直接暴露为一个模型, 因此不能像操作其他模型那样直接操作它.

如果需要访问或修改中间表的数据, 应该通过ManyToManyField提供的API来进行, 比如使用: add(), remove(), set()和clear()等方法.
这些方法会自动处理中间表的数据, 而不需要直接操作它.
    # 这种方式需要多次查询数据库
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.author.add(1)

    book_obj = models.Book.objects.filter(pk=2).first()
    book_obj.author.add(2)

    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.author.add(3)

    book_obj = models.Book.objects.filter(pk=4).first()
    book_obj.author.add(1, 2)
使用in查询来一次性获取多本书, 然后遍历这些书并为它们添加作者.
这样可以减少数据库查询的次数, 从而提高效率.
import os

if __name__ == "__main__":
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyDjango.settings')
    import django

    django.setup()

    from library.models import Book

    # 执行一次查询
    books = Book.objects.filter(pk__in=[1, 2, 3, 4])
    for book in books:
        if book.pk == 1:
            res = book.author.add(1)  # 第一本书添加ID为1的作者
            print(res)
        elif book.pk == 2:
            res = book.author.add(2)  # 第二本书添加ID为2的作者
            print(res)
        elif book.pk == 3:
            res = book.author.add(3)  # 第三本书添加ID为3的作者
            print(res)
        elif book.pk == 4:
            res = book.author.add(1, 2)  # 第四本书添加ID为1, 2的作者
            print(res)
	

image-20240726001049820

image-20240726002029117

1.6 静态文件配置

项目中需要使用到jQuery(3.7.1)框架与bootstrap(3.3.7)框架.

jQuery文件下载地址: https://code.jquery.com/jquery-3.7.1.min.js , 将代码复制到本地文件.
bootstrap框架下载地址: https://v3.bootcss.com/getting-started/#download .
静态文件配置步骤:
* 1. 项目目录下创建static目录.
* 2. settings.py配置文件中开放静态文件的路径.
STATIC_URL = '/static/'
# 静态文件目录
STATICFILES_DIRS = [
    BASE_DIR / 'static'
]

image-20240725190936399

* 3. static目录下创建js目录, 复制jQuery文件到js目录中.
* 4. 复制bootstrap到static目录下.

image-20240725192959807

2. 主页

* 1. 在项目配置目录的路由文件中设置路由分发.
* 2. 在应用的目录下创建子路由文件.
* 3. 编写路由与视图函数的对应关系.
* 4. 在视图层中写视图函数处理请求.
* 5. 编写视图函数放回的主页面.

2.1 路由层

在项目配置目录的路由文件中设置路由分发.
# MyDjango/MyDjango/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    # 设置子路由
    path('', include(('library.urls', 'library'), namespace='library'))
]

image-20240801131230358

在应用的目录下创建子路由文件并编写路由与视图函数的对应关系, 主页面使用根目录(/), 也就是: http://127.0.0.1:8000/ . 
# library/urls.py
from django.urls import path
from library.views import home

urlpatterns = [
    # 主页面
    path('', home, name='library')
]

image-20240801134409768

2.2 视图层

主页面视图返回一个home主页面.
# library/view.py
from django.shortcuts import render


# 主页面视图
def home(request):
    return render(request, 'home.html', locals())

image-20240801134435469

2.3 模板层

2.3.1 模板页面
1. 在templates目录下创建base模板页面.
2. 在页面中导入jQuery与bootstrap文件.
3. 在页面中划分css, html, js三个块, 用于模板继承.
4. 在templates目录下创建home页面并继承base模板页面.
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书管理系统</title>
    <!-- 加载静态文件-->
    {% load static %}
    <script src="{% static 'js/jquery.js' %}"></script>
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>

    <!-- css局部修改区域 -->
    {% block css %}

    {% endblock %}
</head>
<!-- 使用宽松布局 -->
<body class="container-fluid">
<!-- html局部修改区域 -->
{% block html %}

{% endblock %}

<!-- js局部修改区域 -->
{% block js %}

{% endblock %}
</body>
</html>

image-20240801233941369

<!-- templates/home.html -->
{% extends "base.html" %}

image-20240801201216571

2.3.2 导航栏
在base模板页面中添加一个导航条, 代码如下(这里只是为了装饰页面, 大部分功能没有实现):
<!-- 导航条, bg-info蓝色背景 -->
<nav class="navbar bg-info">
    <!-- 全宽布局, 导航栏的元素排列间隙大 -->
    <div class="container-fluid">
        <!-- 导航栏标题 -->
        <div class="navbar-header">
            <!-- 导航栏默认是折叠的. 点击这个按钮时, 会移除collapsed类, 表示导航栏已展开. -->
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <!-- 这三个span元素通过CSS样式被渲染成三条横线, 用于在小屏幕设备上表示导航栏的展开/收起状态. -->
                <span class="sr-only">切换导航</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">图书馆</a>
        </div>

        <!-- 导航栏内容, 包裹了导航栏中应该在较小屏幕设备上折叠起来的所有内容, 通过带有navbar-toggler类的按钮控制 -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <!-- 下拉列表 -->
            <ul class="nav navbar-nav">
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                       aria-haspopup="true" aria-expanded="false">我的收藏<span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Python</a></li>
                        <li><a href="#">MySQL</a></li>
                        <li><a href="#">Linux</a></li>
                    </ul>
                </li>
            </ul>
            <!-- 搜索框 -->
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="输入并搜索...">
                </div>
                <button type="submit" class="btn btn-default">搜索</button>
            </form>
            <!-- 下拉列表-->
            <ul class="nav navbar-nav navbar-right">
                <li>
                    <a href="#">收藏本页面</a>
                </li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
                       aria-haspopup="true" aria-expanded="false">背景<span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">浅绿色</a></li>
                        <li><a href="#">浅粉色</a></li>
                        <li><a href="#">浅黄色</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>

2024-08-01_234105

启动项目, 访问: http://127.0.0.1:8000/ , 目前的主页面效果如下:

image-20240801234221374

2.3.3 页面内容
* 1. 页面内容使用栅格布局3-9.
* 2. 栅格左边部分存放一个功能选项侧边栏并存放多个功能选项, 还实现点击列表项时使其高亮显示.
* 3. 栅格右边部分放一个功能展示面板, 面板含有面板标题和面板内容两个区域, 将面板内容作为可替换区域.
<!-- 页面内容使用3-9布局 -->
<div class="row">

    <!-- 功能选项侧边栏 -->
    <div class="col-md-3">
        <div class="list-group">
            <a href="/" class="list-group-item active">首页</a>
            <a href="#" class="list-group-item">书籍列表</a>
            <a href="#" class="list-group-item">出版社列表</a>
            <a href="#" class="list-group-item">作者列表</a>
            <a href="#" class="list-group-item">更多</a>
        </div>
    </div>

    <!-- 功能展示面板 -->
    <div class="col-md-9">
        <div class="panel panel-primary">
            <!-- 标题-->
            <div class="panel-heading">
                <h3 class="panel-title">
                    <!-- 面板标题修改区域 -->
                    {% block panel_title %}

                    {% endblock %}
                </h3>
            </div>
            <!-- 内容-->
            <div class="panel-body">
                <!--  面板主题修改区域 -->
                {% block panel_body %}

                {% endblock %}
            </div>
        </div>
    </div>

</div>

202408020837434

这段代码的主要作用是在网页上创建一个带有响应式布局的侧边栏或导航栏, 用于引导用户访问网站的不同部分或功能.
其中包含了五个链接选项: '首页', '图书列表', '出版社列表', '作者列表''更多'.
而内容展示区则通过面板来展示链接选项的内容.
启动项目, 访问: http://127.0.0.1:8000/ , 目前的主页面效果如下:

202408012345067

为列表项添加模板标签, 根据请求的URL来决定哪个列表项应该被高亮(active类为激活状态有高亮效果, disabled为禁用状态不可选中).
<div class="list-group">
    <a href="/"
       class="list-group-item {% if request.path  == '/' %} active {% endif %}">首页</a>
    <a href=""
       class="list-group-item {% if request.path == '/book_list' %} active {% endif %}">书籍列表</a>
    <a href="#"
       class="list-group-item {% if request.path == '/publish_list' %} active {% endif %}">出版社列表</a>
    <a href="#"
       class="list-group-item {% if request.path == '/author_list' %} active {% endif %}">作者列表</a>
    <a href="#" class="list-group-item disabled">更多</a>
</div>

202408021533856

启动项目, 访问主页: 127.0.0.1:8000 , 查看高亮效果:

202408021540365

列表项的a标签通过反向解析生成url, 必须先在路由层创建好路由, 模板层中才能使用, 否则会报错.
还没有填写url地址的列表项还不能点击.
2.3.4 主页面板
主页面面板是访问主页面默认展示的信息.
在home页面中继承base.html页面, 并重新定义css, panel_title, panel_body三个块的内容.
在css块中自定义一个响应式类, 确保图片在不同屏幕尺寸下保持良好的布局和显示.
在panel_title块中定义面板的名称.
在panel_body块中展示一个一个轮转图和三张缩略图.
轮转图的三张图片连接:
1. https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FCNJFHvDlquibBda.jpg&pos_id=img-S9SIts4y-1722648817610)
2. https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FAWzJVDgPKlc8OZt.jpg&pos_id=img-ZCuvdZg2-1722648821936)
3. https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FIZlAELwBqPFjspU.jpg&pos_id=img-jb56HOte-1722648831450)

缩略图的三张图片连接:
1. https://s2.loli.net/2022/03/10/I4ziahsHbWCAkJU.jpg
2. https://s2.loli.net/2022/03/10/fFm9Lu2hkQRoJNg.jpg
3. https://s2.loli.net/2022/03/10/8ojETnzqRkLyG6h.jpg

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1646919596(1)_副本

banner1_副本 1646921174(1)_副本 1646921220(1)_副本
主页的信息就不写进去数据库了直接在html中写().
<!-- 继承模板页码 -->
{% extends "base.html" %}

<!-- 继承css块 -->
{% block css %}
    <style>
        /* 图片的响应式工具类, 它确保图片能够在不同屏幕尺寸下保持良好的布局和显示 */
        .img-fluid {
            width: 100%;
            height: auto;
        }
    </style>
{% endblock %}

<!-- 继承面板标题块 -->
{% block panel_title %}主页功能展示{% endblock %}


<!-- 继承面板主体块 -->
{% block panel_body %}
    <!-- 轮转图 -->
    <div>
        <div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
            <!-- 指标 -->
            <ol class="carousel-indicators">
                <li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
                <li data-target="#carousel-example-generic" data-slide-to="1"></li>
                <li data-target="#carousel-example-generic" data-slide-to="2"></li>
            </ol>

            <!-- 幻灯片装饰器 -->
            <div class="carousel-inner " role="listbox">
                <div class="item active ">
                    <!--style="width: 100%;"是图片铺满转轮图-->
                    <img src="https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FCNJFHvDlquibBda.jpg&pos_id=img-S9SIts4y-1722648817610)" alt="..." class="img-fluid">
                </div>
                <div class="item">
                    <img src="https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FAWzJVDgPKlc8OZt.jpg&pos_id=img-ZCuvdZg2-1722648821936)" alt="..." class="img-fluid">
                </div>
                <div class="item">
                    <img src="https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fs2.loli.net%2F2022%2F03%2F10%2FIZlAELwBqPFjspU.jpg&pos_id=img-jb56HOte-1722648831450)" alt="..." class="img-fluid">
                </div>
            </div>

            <!-- 控制 -->
            <a class="left carousel-control" href="#carousel-example-generic" role="button"
               data-slide="prev">
                <span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
                <!-- class="sr-only 这个类通常用于屏幕阅读器(Screen Readers), 它对于视觉用户是不可见的. -->
                <span class="sr-only">上一页</span>
            </a>
            <a class="right carousel-control" href="#carousel-example-generic" role="button"
               data-slide="next">
                <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
                <span class="sr-only">下一页</span>
            </a>
        </div>
    </div>
    <br>
    <!-- 缩略图 -->
    <div>
        <div class="row">
            <div class="col-sm-6 col-md-4">
                <div class="thumbnail">
                    <img src="https://s2.loli.net/2022/03/10/I4ziahsHbWCAkJU.jpg" alt="...">
                    <div class="caption">
                        <h3>Python</h3>
                        <p>由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计, 作为一门叫做ABC语言的替代品.
                            Python提供了高效的高级数据结构, 还能简单有效地面向对象编程...</p>
                        <p><a href="#" class="btn btn-primary" role="button">关注</a> <a
                                href="#" class="btn btn-default" role="button">收藏</a></p>
                    </div>
                </div>
            </div>

            <div class="col-sm-6 col-md-4">
                <div class="thumbnail">
                    <img src="https://s2.loli.net/2022/03/10/fFm9Lu2hkQRoJNg.jpg" alt="...">
                    <div class="caption">
                        <h3>MySQL</h3>
                        <p>是最流行的关系型数据库管理系统,
                            在WEB应用方面MySQL是最好的RDBMS(关系数据库管理系统)应用软件之一...</p>
                        <p><a href="#" class="btn btn-primary" role="button">关注</a>
                            <a href="#" class="btn btn-default" role="button">收藏</a></p>
                    </div>
                </div>
            </div>

            <div class="col-sm-6 col-md-4">
                <div class="thumbnail">
                    <img src="https://s2.loli.net/2022/03/10/8ojETnzqRkLyG6h.jpg" alt="...">
                    <div class="caption">
                        <h3>Linux</h3>
                        <p>
                            全称GNU/Linux, 是一套免费使用和自由传播的类UNIX操作系统, 它主要受到Minix和Unix思想的启发,
                            是一个基于POSIX和Unix的多用户, 多任务, 支持多线程和多CPU的操作系统...</p>
                        <p><a href="#" class="btn btn-primary" role="button">Button</a> <a
                                href="#" class="btn btn-default" role="button">Button</a></p>
                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock %}

2024-08-01_231740

启动项目, 访问: http://127.0.0.1:8000/ , 主页面效果如下:

202408012347838

3. 书籍列表

3.1 路由层

在子路由中添加一个路由, 当用户访问: 127.0.0.1:8000/book_list时展示书籍信息.
# library/urls.py
from django.urls import path
from library.views import home, book_list

urlpatterns = [
    # 主页面
    path('', home, name='library'),
    # 书籍列表
    path('book_list', book_list, name='book_list')
]

image-20240801235917702

3.2 视图层

视图函数中读取数据库中的所有的书籍实例并返回给book_list页面(现在数量量少, 先不考虑分页的问题).
# library/views.py
from django.shortcuts import render
# 导入模型
from library.models import Book


# 书籍列表
def book_list(request):
    # 读取所有书籍实例
    books = Book.objects.all()
    # 返回页面与书籍实例
    return render(request, 'book_list.html', locals())

image-20240802045118133

3.3 模板层

书籍列表面板展示所有书籍的信息.
1. 在侧边栏的书籍列表中绑定访问地址为.
2. 在templates目录下创建book_list.html页面.
3. 在书籍列表页面中继承base.html页面, 并重新定义css, panel_title, panel_body三个块的内容.
4. 在css块中自定义一个类, 让表格的每行文字垂直对齐(默认向上对齐不怎么好看).
5. 在panel_title块中定义面板的名称.
6. 在panel_body块中使用表格展示书籍信息, 表单展示的信息如下:
序号编号书名作者出版社出版日期价格操作按钮
1书籍id号唯一可能有多个唯一唯一唯一编辑 删除
<!-- 在base.html中为图书列表选项的绑定url地址 -->
<a href="{% url 'library:book_list' %}"
   class="list-group-item {% if request.path == '/book_list' %} active {% endif %}">书籍列表</a>

202408021543960

<!-- templates/book_list.html -->
<!-- 继承模板页码 -->
{% extends "base.html" %}

{% block css %}
    <style>
        .table > tbody > tr > td {
            vertical-align: middle;
        <!-- 书籍信息在表格中垂直对齐 -->
        }
    </style>

{% endblock %}
<!-- 继承面板标题块 -->
{% block panel_title %}书籍信息{% endblock %}

<!-- 继承面板主体块 -->
{% block panel_body %}
    <!-- 表单. table-striped表单条纹, table-hover:鼠标悬停效果-->
    <table class="table table-striped table-hover">
        <thead>
        <tr>
            <th>序号</th>
            <th>编号</th>
            <th>书名</th>
            <th>作者</th>
            <th>出版社</th>
            <th>出版时间</th>
            <th>价格</th>
            <th>操作</th>
        </tr>
        </thead>
        <!-- 遍历书籍实例 -->
        <tbody>
        {% for book in  books %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ book.pk }}</td>
                <td>{{ book.title }}</td>
                <td>
                    {% for author_obj in book.author.all %}
                        <!--每个遍历循环都有一个forloop对象-->
                        {% if forloop.last %}  <!-- 判断当前的作者对象是否为最后一个遍历的元素 --->
                            {{ author_obj.name }} 
                        {% else %}
                            {{ author_obj.name }},
                        {% endif %}
                    {% endfor %}
                </td>
                <td>{{ book.publish.name }}</td>
                <td>{{ book.publication_date|date:'Y-m-d' }}</td>
                <td>{{ book.price }}</td>
                <td>
                    <a href="" class="btn btn-primary btn-sm">编辑</a>
                    <a href="" class="btn btn-danger btn-sm">删除</a>
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
{% endblock %}

image-20240802071956402

启动项目, 访问: http://127.0.0.1:8000/book_list , 书籍列表页面效果如下:

image-20240802160902891

4. 添加书籍

4.1 路由层

在子路由中添加一个路由, 当用户访问: 127.0.0.1:8000/book_add时展示书籍添加页面.
# library/urls.py
from django.urls import path
from library.views import home, book_list, book_add

urlpatterns = [
    # 主页面
    path('', home, name='library'),
    # 书籍列表
    path('book_list', book_list, name='book_list'),
    # 书籍添加
    path('book_add', book_add, name='book_add')
]

image-20240802202743606

4.2 视图层

先分析添加书籍表单中需要的信息:
* 1. id字段 , 自增不用管.
* 2. title书名字段, 需要表单提供. 
* 3. price书籍价格字段, 需要表单提供.                     
* 4. publication_date出版时间, 自动添加不用管.  
* 5. 外键字段publish, 使用已经存在的出版社.
* 6. 外键字段author, 使用已经存在的作者.
视图需要读取数据库中的作者表和出版社表的数据再与添加图书页面一同返回.
# library/views.py
from django.shortcuts import render
# 导入模型
from library.models import Book, Publish, Author


def book_add(request):
    # 获取所有的出版社实例
    publishing = Publish.objects.all()
    # 获取所有的作者实例
    authors = Author.objects.all()

    return render(request, 'book_add.html', locals())

image-20240802162522633

4.3 模板层

1. 在base.html模板页面的侧边栏中添加一个列表项.
2. 在templates目录下创建book_add.html页面.
3. 在添加书籍页面中继承base.html页面, 并重新定义panel_title, panel_body两个块的内容.
4. 在panel_title块中定义面板的名称.
5. 在panel_body块中添加一个表单用于收集书籍信息, 收集的信息如下:
* 1. id字段 , 自增不用管.
* 2. title书名字段, 需要表单提供, 使用input输入框, 名称为: title.
* 3. price书籍价格字段, 需要表单提供, 使用input输入框, 名称为: price.               
* 4. publication_date出版时间字段, 自动添加(数据插入的时间).
* 5. 外键字段publish, 使用已经存在的出版社, 使用下拉框, 名称为: publish_id, 并设置单选, 展示的是出版社的名称提交的是出版社id. 
* 6. 外键字段author, 使用已经存在的作者, 使用下拉框, 名称为: publish_id, 并设置多选, 展示的是作者的名称提交的是作者id. 
<!-- base.html的侧边栏中添加一个列表项 -->
<a href="{% url 'library:book_add' %}"
   class="list-group-item {% if request.path == '/book_add' %} active {% endif %}">添加书籍</a>

2024-08-02_195959

<!-- templates/book_add.html -->

<!-- 继承模板页码 -->
{% extends "base.html" %}

<!-- 继承面板标题块 -->
{% block panel_title %} 书籍添加 {% endblock %}

<!-- 继承面板主体块 -->
{% block panel_body %}

    <!-- 表单 -->
    <form action="" method="post">
        <div class="input-group">
            <span class="input-group-addon">书名:</span>
            <input type="text" class="form-control mt-5" placeholder="书籍名称" name="title">
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">价格:</span>
            <input type="text" class="form-control" placeholder="书籍价格" name="price">
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">出版社:</span>
            <select name="publish_id" class="form-control">
                <!--selected默认选中, disabled不可手动选中, hidden隐藏选项-->
                <option selected disabled hidden>点击选择</option>
                {% for publish in publishing %}
                    <option value="{{ publish.pk }}">{{ publish.name }}</option>
                {% endfor %}

            </select>
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">作者:</span>
            <select name="author_id" multiple="multiple" class="form-control">
                {% for author in authors %}
                    <option value="{{ author.pk }}">{{ author.name }}</option>
                {% endfor %}
            </select>
        </div>
        <br>

        <p>
            <input type="submit" value="添加" class="btn btn-primary form-control">
        </p>
    </form>
    
{% endblock %}

image-20240802215110434

启动项目, 访问: http://127.0.0.1:8000/book_add , 查看添加书籍页面的效果:

image-20240802204810661

4.4 写入数据

1. 修改视图函数, 从POST请求提交的表单中获取书籍信息.
2. 需要为两张表写入数据(表单中提交的数据都是字符串, 在写入数据库的时候会自动转换类型.)
   首先, 往书籍表中写数据(需要为title, price, publish_id三个字段提供值).
   最后, 使用书籍对象的author外键字段获取到书籍作者关联表, 再使用set()方法添加多对多关联.
   set()方法允许传递一个可迭代对象(比如列表, 元组等), 它会遍历这个可迭代对象, 并逐个添加其中的元素.
3. 写入成功后重定向到书籍列表页面.
# library/views.py
from django.shortcuts import render, redirect
# 导入模型
from library.models import Book, Publish, Author


# 添加书籍
def book_add(request):
    # 处理GET请求:
    if request.method == 'GET':
        # 获取所有的出版社实例
        publishing = Publish.objects.all()
        # 获取所有的作者实例
        authors = Author.objects.all()

        return render(request, 'book_add.html', locals())

    # 处理POST请求:
    if request.method == 'POST':
        # 获取书籍信息
        title = request.POST.get('title')
        price = request.POST.get('price')
        publish_id = request.POST.get('publish_id')
        # 作者id有多个, 通过getlist方法获取, 值是一个列表
        author_id = request.POST.getlist('author_id')

        # 数据校验跳过
        # print(title, price, publish_id, author_id)

        # 创建书籍实例
        book = Book.objects.create(title=title, price=price, publish_id=publish_id)
        # # 添加多对多关联
        book.author.set(author_id)
        # 重定向到书籍列表页面
        return redirect('/book_list')

image-20240803000628196

启动项目, 访问: http://127.0.0.1:8000/book_add , 填写信息并提交.

image-20240802214926019

实例添加成功之后, 会跳转到书籍列表页面, 可以查看新添加的书籍记录.

image-20240802215440597

5. 书籍修改

编辑书籍信息的思路:
* 1. 给编辑按钮绑定请求地址, 在书籍列表中点击修改时, 提交一个get请求, 并携带书籍的id.
* 2. 路由中使用转换器获取id值并传递给视图函数.
* 3. 后端处理请求, 并通过书籍id获取对应书籍实例数据, 返回一个书籍修改页面和需要修改的书籍实例.
* 4. 书籍修改页面中展示一个表单, 表单中展示可修改的书籍信息.

5.1 路由层

在子路由中添加一个路由, 当用户访问: 127.0.0.1:8000/book_set/id时展示书籍修改页面.
请求地址携带了书籍id, 可以通过内置的转换器来捕获获取这个值.
# library/urls.py
from django.urls import path
from library.views import home, book_list, book_add, book_set

urlpatterns = [
    # 主页面
    path('', home, name='library'),
    # 书籍列表
    path('book_list', book_list, name='book_list'),
    # 书籍添加
    path('book_add', book_add, name='book_add'),
    # 书籍修改
    path('book_set/<int:book_id>', book_set, name='book_set')
]

image-20240802223059777

5.2 视图层

修改数据页面需要获取所有的出版社信息和作者信息和修改的书籍信息, 在视图中获取并返回.
# library/views.py

# 书籍修改, 需要接收内置转换器传递的参数
def book_set(request, book_id):
    # 处理GET请求:
    if request.method == 'GET':
        # 获取所有的出版社实例
        publishing = Publish.objects.all()
        # 获取所有的作者实例
        authors = Author.objects.all()
        # 获取书籍实例
        book = Book.objects.filter(id=book_id).first()
        return render(request, 'book_set.html', locals())

image-20240802233425232

5.3 模板层

在book_list.html页面中为编辑按钮绑定跳转地址, 提交的get请求携带书籍实例的id.
<!-- templates/book_list.html -->
<!-- book.pk前面不需要添加/url模板标签会自动处理URL的生成, 只需要提供正确的参数即可,  -->
<a href="{% url 'library:book_set'  book.pk %}" class="btn btn-primary btn-sm">编辑</a>

2024-08-02_234615

在book_set.html页面中展示书籍实例的信息, 通过{% if %}标签可以对外键字段进行默认选中.
<!-- templates/book_set.html -->
<!-- 继承模板页码 -->
{% extends "base.html" %}

<!-- 继承面板标题块 -->
{% block panel_title %} 书籍信息修改 {% endblock %}

<!-- 继承面板主体块 -->
{% block panel_body %}
    <!-- 表单  -->
    <form action="" method="post">
        {% csrf_token %}
        <div class="input-group">
            <span class="input-group-addon">书名:</span>
            <input type="text" class="form-control mt-5" placeholder="书籍名称" name="title" value="{{ book.title }}">
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">价格:</span>
            <input type="text" class="form-control" placeholder="书籍价格" name="price" value="{{ book.price }}">
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">出版社:</span>
            <select name="publish_id" class="form-control">
                {% for publish in publishing %}
                    <!-- 如果出版社id是书籍实例的外键则默认选中 -->
                    {% if publish.id == book.publish_id %}
                        <option selected value="{{ publish.pk }}">{{ publish.name }}</option>
                    {% else %}
                        <option value="{{ publish.pk }}">{{ publish.name }}</option>
                    {% endif %}
                {% endfor %}

            </select>
        </div>
        <br>

        <div class="input-group">
            <span class="input-group-addon">作者:</span>
            <select name="author_id" multiple="multiple" class="form-control">
                {% for author in authors %}
                    <!--all()获取的是queryset对象, 判断author实例是否在queryset对象中, 如果中则默认选中-->
                    {% if author in book.author.all %}
                        <option selected value="{{ author.pk }}">{{ author.name }}</option>
                    {% else %}
                        <option value="{{ author.pk }}">{{ author.name }}</option>
                    {% endif %}
                {% endfor %}
            </select>
        </div>
        <br>

        <p>
            <input type="submit" value="提交" class="btn btn-primary form-control">
        </p>
    </form>

{% endblock %}

image-20240802234825192

启动项目, 访问: 127.0.0.1:8000/book_list , 选中一书籍并点击编辑按钮.

image-20240802235034947

点击编辑后访问: 127.0.0.1:8000/book_set/4 , 书籍修改页面展示如下:

5.4 修改数据

1. 修改视图函数, 从POST请求提交的表单中获取书籍信息.
2. 需要为两张表更新数据(表单中提交的数据都是字符串, 在写入数据库的时候会自动转换类型.)
   首先, 获取书籍对象, 使用update更新字段: title, price, publish_id的值. 
   最后, 使用书籍对象的author外键字段获取到书籍作者关联表, 再使用set()方法修改多对多关联.
   set()方法允许传递一个可迭代对象(比如列表, 元组等), 它会遍历这个可迭代对象, 并逐个添加其中的元素.
3. 修改成功后重定向到书籍列表页面.
# library/views.py

# 书籍修改, 需要接收内置转换器传递的参数
def book_set(request, book_id):
    # 处理GET请求:
    if request.method == 'GET':
        # 获取所有的出版社实例
        publishing = Publish.objects.all()
        # 获取所有的作者实例
        authors = Author.objects.all()
        # 获取书籍实例
        book = Book.objects.filter(id=book_id).first()
        return render(request, 'book_set.html', locals())

    # 处理POST请求:
    if request.method == 'POST':
        # 获取书籍信息
        title = request.POST.get('title')
        price = request.POST.get('price')
        publish_id = request.POST.get('publish_id')
        # 作者id有多个, 通过getlist方法获取, 值是一个列表
        author_id = request.POST.getlist('author_id')

        # 数据校验跳过
        # print(title, price, publish_id, author_id)

        # 获取书籍实例, update是queryset对象方法
        query_set = Book.objects.filter(id=book_id)
        # 更新书籍实例
        query_set.update(title=title, price=price, publish_id=publish_id)
        # 通过first()方法获取书籍实例, 在通过author外键更新多对多关联
        query_set.first().author.set(author_id)
        # 重定向到书籍列表页面
        return redirect('/book_list')

image-20240803011553905

启动项目, 访问两次: 127.0.0.1:8000/book_list/4 , 获取书籍id为4的修改页面, 一个做参考一个做修改并提交请求.

image-20240803011008594

修改成功之后, 跳转到书籍列表页面中, 查看修改后的书籍信息.

image-20240803011518363

访问注点意:
修改页面的路由是: 'book_set/<int:book_id>' .
视图函数的定义为: def book_set(request, book_id) .
点击编辑的时候, 访问book_set页面需要携带一个id值为路径, 视图函数也始终接收被转换器捕获的id值路径.
例如访问: 127.0.0.1:8000/book_list/4 , 返回一个书籍修改页面.
当修改信息完成后, 表单向当前的url地址(127.0.0.1:8000/book_list/4)提交POST请求.
上诉过程中, 请求地址中一直确保着book_id, 否则路由或book_set视图函数会出错.

6. 删除书籍

删除书籍信息的思路:
* 1. 给删除按钮绑定请求地址, 在书籍列表中点击删除时, 提交一个get请求, 并携带书籍的id.
* 2. 路由中使用转换器获取id值并传递给视图函数.
* 3. 后端处理请求, 并通过书籍id删除对应书籍实例数据.
* 4. 删除数据后跳转到图书列表中.

6.1 路由层

在子路由中添加一个路由, 当用户访问: 127.0.0.1:8000/book_delete/id时展示书籍修改页面.
请求地址携带了书籍id, 可以通过内置的转换器来捕获获取这个值.
# library/urls.py

from django.urls import path
from library.views import home, book_list, book_add, book_set, book_delete

urlpatterns = [
    # 主页面
    path('', home, name='library'),
    # 书籍列表
    path('book_list', book_list, name='book_list'),
    # 书籍添加
    path('book_add', book_add, name='book_add'),
    # 书籍修改
    path('book_set/<int:book_id>', book_set, name='book_set'),
    # 书籍删除
    path('book_delete/<int:book_id>', book_delete, name='book_delete'),
]

image-20240803004322902

6.2 视图层

在视图直接通过书籍id删除实例, 然后重定向到书籍列表页面.
# library/views.py

# 书籍删除
def book_delete(request, book_id):
    # 通过书籍主键删除实例
    Book.objects.filter(id=book_id).delete()
    # 重定向到书籍列表页面
    return redirect('/book_list')

image-20240803011904961

6.3 模型层

在book_list.html页面中为删除按钮绑定跳转地址, 提交的get请求携带书籍实例的id.
<!-- templates/book_list.html -->

<a href="{% url 'library:book_delete'  book.pk %}" class="btn btn-danger btn-sm">删除</a>

2024-08-03_005157

启动项目, 访问: 127.0.0.1:8000/book_list, 选中一个书籍实例并点击删除.

image-20240803011716679

删除成功之后, 跳转到书籍列表页面中, 查看删除后的书籍信息.

image-20240803011741742

7. 页面背景

在模板页面中写写一个js替换body的背景颜色.

<!-- 背景色修改 -->
<script>
    $(document).ready(function () {
        // 监听下拉框中链接的点击事件
        $('.dropdown-menu a').click(function (e) {
            e.preventDefault(); // 阻止链接的默认跳转行为
            // 移除body上已有的背景类(如果有的话)
            var $body = $('body');
            $body.removeClass('bg-success bg-danger bg-warning');
            // 根据点击的链接文本添加相应的背景类
            var text = $(this).text();
            switch (text) {
                case '浅绿色':
                    $body.addClass('bg-success');
                    break;
                case '浅粉色':
                    $body.addClass('bg-danger');
                    break;
                case '浅黄色':
                    $body.addClass('bg-warning');
                    break;
            }
        });
    });
</script>

image-20240803014842185

启动项目, 访问任意一个页面, : 127.0.0.1:8000/book_list , 在导航栏中设置页面的背景颜色, 刷新页面则恢复默认的白色.

GIF 2024-8-3 1-51-24

出版社列表与作者表有兴趣自己去完善.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1988849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试题:Java 集合类的遍历方式,如何一边遍历 一边删除?

问题一&#xff1a;你用过 Java 中的哪些集合类&#xff1f; ArrayList, LinkedList, HashMap, HashSet, TreeSet, Stack, Queue, PriorityQueue等 问题二&#xff1a;集合中遍历元素的方式&#xff1f; Collection 接口实现子类 1. List 集合 // list 集合public static …

【Linux】进程间通信(管道通信、共享内存通信)

一.什么是进程间通信 进程间通信这五个字很好理解&#xff0c;就是进程和进程之间通信。 那么为什么要有进程间通信呢&#xff1f; 1.数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 2.资源共享&#xff1a;多个进程之间共享同样的资源 3.通知事件&#xff1a;一…

如何制作自己的python .whl包(支持entry_points)

目录 代码目录结构如下截图所示&#xff1a;dir_test.py 源码如下&#xff1a;list/dir_list.py 源码如下&#xff1a;setup.py 文件源码生成.whl文件指令&#xff1a; 代码目录结构如下截图所示&#xff1a; dir_test.py 源码如下&#xff1a; import os import sys from pat…

RunAsDate(时间限制工具)

参考链接1 参考链接2 参考链接3 下载地址 ps&#xff1a;64位系统需要下载64的RunAsDate

LAMP架构详解

目录 一、Apache详解 1.1 简介 1.2 Apache功能 1.3 apache特点 1.4 三种工作模式 二、LAMP简介 2.1 LAMP平台概述 2.2 构建LAMP平台顺序 2.3 编译安装的优点 2.4 各组件的主要作用 三、wget命令 四、curl命令 五、压力测试工具 一、Apache详解 1.1 简介 Apache …

vue2,v-for中动态渲染本地的图片

一、描述 如果是正常在img标签的src上使用本地的url地址&#xff0c;是可以正常被渲染的&#xff0c;但是我们通过for的形式&#xff0c;动态渲染的话&#xff0c;就会通过网络请求的方式进行渲染&#xff0c;这个形式反而渲染不出来。 二、效果 这个效果&#xff0c;毋庸置…

LVS负载均衡集群部署之—NAT模式的介绍及搭建步骤

一、环境准备 1.准备三台rhel9服务器 服务器名称 主机名 ip地址备注LVS调度服务器lvs.timinglee.org eth0:172.25.254.100&#xff08;外网&#xff09; eth1:192.168.0.100(内网) 关闭selinux和防火墙webserver2网站服务器webserver1.timinglee.orgeth0&#xff1a;192.168.…

为什么高校开设微专业,建议搭建动作捕捉与数字人开发实训室?

随着近年来虚拟现实技术产业与元宇宙产业不断发展&#xff0c;动作捕捉技术成为元宇宙、VR/AR、影视动画、游戏、艺术创作、虚拟偶像等行业相关不可或缺的技术之一。各大院校为了探索新的教学模式&#xff0c;纷纷积极开设“微专业”&#xff0c;相比传统的虚拟仿真实训室来说&…

Linux进程调度与切换

目录 前言 Linux 2.6内核O(1)调度器 调度过程 调度算法 Linux 进程切换 前言 在Linux 2.6版本的内核中&#xff0c;进程调度器引入了O(1)调度器&#xff0c;这个调度器通过优先级队列、活跃队列和过期队列的机制来管理进程调度,虽然在现在已被更好的CFS调度器取代,但对于我…

中仕公考:2024年空军专业技能类文职人员公开招考公告

2024年空军专业技能类文职人员公开招考公告&#xff0c;有关事项公告如下&#xff1a; 一、招考岗位 主要有保管员、司机、炊事员、文印员、汽车修理工兼司机等专业技能三级以下岗位。 二、招考对象 符合岗位资格条件的社会人员(含高校应届毕业生、退役军人)。 根据军队有…

理解栈(Stack)及其在 C++ 中的应用【栈、数据结构】

在这篇博客中&#xff0c;我们将详细介绍栈&#xff08;Stack&#xff09;这一重要的数据结构&#xff0c;包括其基本概念、常用操作、C 中的实现&#xff0c;以及一些实际应用。 什么是栈&#xff1f; 栈是一种数据结构&#xff0c;它遵循“后进先出”&#xff08;LIFO - La…

上海AI Lab 搭台,36个大模型一起角逐长上下文建模能力

现在的大模型论文简直像是在比长度&#xff0c;动不动就上百页&#xff01;记得前阵子小编瞅见那份90页的Gemini技术报告&#xff0c;顿时脑袋嗡嗡作响。那会儿就幻想着&#xff1a;要是有个AI大脑来啃下这些"学术巨无霸"&#xff0c;那岂不是爽歪歪&#xff1f; 没…

SpringDoc:一个用于自动生成API文档的工具

SpringDoc的使用 概述SpringDoc添加依赖配置 Springdoc创建 REST 控制器访问 API 文档添加注释和描述自定义配置常用注解 详细示例创建模型类创建REST控制器查看Swagger UI与OpenAPI 安全策略类型概述HTTPAPIKEYOAUTH2OPENIDCONNECTMUTUALTLS 请求头配置认证token代码实现验证 …

C++:C++11介绍

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一、C11简介 二 统一的列表初始化 2.1 {} 初始化 2.2 std::initializer_list 三 声明 3.1 auto 3.2 decltype 3.3 nullptr 四 范围for循环 五 智能指针 六 STL中一些变化…

瑞_RabbitMQ_初识MQ

文章目录 1 初识MQ1.1 同步调用1.1.1 同步调用的优势1.1.2 同步调用的缺点 1.2 异步调用1.2.1 异步调用的角色1.2.2 异步调用的优势1.2.3 异步调用的缺点1.2.4 异步调用的场景 1.3 MQ技术选型 2 RabbitMQ2.1 安装2.1.1 资源准备2.1.2 安装步骤 2.2 RabbitMQ架构2.3 RabbitMQ管理…

Starrocks解析json数组

json数据 [{"spec": "70g/支","unit": "支","skuId": "1707823848651276346","amount": 6,"weight": 70,"spuName": "伊利 甄稀 苦咖啡味雪糕 流心冰淇淋 70g/支",&quo…

你不知道,PMP证书的含金量究竟有多高

PMP考试的含金量体现在其全球认可度、对职业发展的助力、薪资潜力的提升、系统的知识体系、持续学习的要求以及专业网络的建设等方面。 尽管存在一定的维护成本和市场饱和度问题&#xff0c;PMP认证仍然是项目管理领域内备受推崇的资格证书。 对于追求专业发展和提升项目管理…

【安卓】发送自定义广播

文章目录 发送标准广播发送有序广播 发送标准广播 先定义一个BroadcastReceiver来准备接收广播&#xff0c;新建一个MyBroadcastReceiver。 public class MyBroadcastReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context context, Intent intent) {To…

惊爆!OpenAI 高层发生剧烈动荡!竟然有 3 名元老同时离职,同时,马斯克竟起诉奥特曼“敲诈勒索”, GPT-5 要推迟了?

当今之 OpenAI 可谓是事端频出&#xff0c;波澜迭起。 开端之际&#xff0c;马斯克竟对 OpenAI提起诉讼&#xff0c;随后&#xff0c;重要的元老级高管公开宣告离职&#xff0c;而且还被披露高管领导层内部动荡不安&#xff0c;最终&#xff0c;就连原本定于年底发布的 GPT-5 …