Python Web开发记录 Day16:Django part10 文件上传(完结篇)

名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪)
创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

目录

      • 1、文件上传
      • 2、Excel上传
      • 3、Form和ModelForm回顾
      • 4、Form图片上传
      • 5、ModelForm图片上传(推荐)
      • 6、城市管理

1、文件上传

1.在urls.py中上传列表的路径upload/list/,并告诉该路径指向的视图upload_list

urls.py

import chart as chart
from django.urls import path
from api.views import depart, user, pretty, admin, account, task, order, chart

urlpatterns = [

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    
]

2.在views文件夹下新建upload.py文件,以实现文件上传函数

upload.py

import re
from django.shortcuts import render, HttpResponse


def upload_list(request):
    # GET方法主要用于获取信息,而POST方法则用于提交数据
    if request.method == "GET":
        return render(request, "upload_list.html")  # render函数负责将HTML模板渲染成最终的网页,并将这个网页返回给客户端。
    # 声明图片的对象
    file_object = request.FILES.get("avatar")

    # 分块进行存储
    # file_object.name 意思是图片上传前后保持原名称
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("上传成功")

3.修改layout.html,在templates目录下新建upload_list.html

image-20240319104710655

在layout.html中添加这一句,以便在网站里显示上传文件的列表选项:

<li><a href="/upload/list/">上传文件</a></li>

upload_list.html

{% extends 'layout.html' %}

{% block content %}

<div class="container">
    <!--method为post,说明此处表单是提交数据-->
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <input type="text" name="name">
        <input type="file" name="avatar">
        <input type="submit" value="提交">
    </form>

</div>

{% endblock %}

上传文件

image-20240319104412794

浏览器进行响应

image-20240319104449051

此时就能发现,文件夹下多了一张咱们上传的图片。

image-20240319104921742

基础的文件上传操作,咱们了解之后,之后来实现一下Excel表格上传。

2、Excel上传

目标:表格上传—》服务器读取保存—》数据库。

以部门管理为例,来进行操作。

1.编辑depart_list.html,增加文件上传板块。

depart_list.html

{% extends 'layout.html' %}
{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px">
            <a class="btn btn-success" href="/depart/add/">
                <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                新建部门
            </a>
        </div>

        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span>
                <span>文件上传</span>
            </div>
            <div class="panel-body">
                <form method="post" enctype="multipart/form-data" action="/depart/multi/">
                    {% csrf_token %}
                    <div class="form-group">
                        <input type="file" name="exc">
                    </div>
                    <input type="submit" class="btn btn-sm btn-info" value="上传">
                </form>
            </div>
        </div>

        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">
                <span class="glyphicon glyphicon-list" aria-hidden="true"></span>
                部门列表
            </div>

            <!-- Table -->
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>名称</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for obj in queryset %}
                    <tr>
                        <th>{{ obj.id }}</th>
                        <td>{{ obj.title }}</td>
                        <td>
                            <a class="btn btn-primary btn-xs" href="/depart/{{ obj.id }}/edit/">编辑</a>
                            <a class="btn btn-danger btn-xs" href="/depart/delete/?nid={{ obj.id }}">删除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
{% endblock %}

2.安装openpyxl

pip install openpyxl

image-20240319110116930

补充:openpyxl是什么?

openpyxl是一个Python库,用于读取和写入Excel 2010 xlsx/xlsm/xltx/xltm文件。这个库允许你以编程方式操作Excel文件,比如创建新的工作簿、读取已有的工作簿、添加或删除工作表、修改单元格数据以及制作图表等。由于openpyxl能够处理Excel文件,它在数据分析和自动化办公中尤其有用,为处理电子表格数据提供了很大的便利。

主要特性包括:

  • 读取和写入Excel 2010 xlsx/xlsm文件。
  • 修改工作簿和工作表,包括添加和删除工作表。
  • 读取和修改单元格内容。
  • 支持图表、图像和表格的创建和编辑。
  • 样式和格式化,包括对文本和单元格的字体、边框、颜色等属性的设置。

通过openpyxl用户可以不依赖于Microsoft Excel应用程序,就能在Python脚本或应用中自动处理Excel文件。

3.在urls.py中上传列表的路径depart/multi/,并告诉该路径指向的视图depart_multi

urls.py

import chart as chart
from django.urls import path
from api.views import depart, user, pretty, admin, account, task, order, chart, upload

urlpatterns = [

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    path('depart/multi/',depart.depart_multi),
]

4.修改depart.py,增加depart_multi文件上传函数。

depart.py

from django.shortcuts import render, redirect, HttpResponse
from api import models
from api.models import Department
from api.utils.pagination import Pagination
from openpyxl import load_workbook


def depart_list(request):
    """部门列表"""
    queryset = models.Department.objects.all()

    page_object = Pagination(request, queryset, page_size=2)
    page_object.html()

    context = {
        "queryset": page_object.page_queryset,
        "page_string": page_object.page_string,
    }
    return render(request, 'depart_list.html', context)


def depart_add(request):
    """添加部门"""
    if request.method == "GET":
        return render(request, 'depart_add.html')

    # 获取用户POST提交过来的数据(title输入为空)
    title = request.POST.get("title")

    # 保存到数据库
    models.Department.objects.create(title=title)

    # 重定向回部门列表
    return redirect("/depart/list/")


def depart_delete(request):
    """删除部门"""
    # 获取ID
    # http://127.0.0.1:8000/depart/delete/?nid=1
    nid = request.GET.get('nid')

    models.Department.objects.filter(id=nid).delete()
    # 重定向回部门列表
    return redirect("/depart/list")


def depart_edit(request, nid):
    """修改部门"""
    if request.method == "GET":
        # 根据nid,获取他的数据[obj,]
        row_object = models.Department.objects.filter(id=nid).first()
        return render(request, 'depart_edit.html', {"row_object": row_object})
    # 获取用户的标题
    title = request.POST.get("title")
    # 根据ID找到数据库中的数据进行更新
    models.Department.objects.filter(id=nid).update(title=title)
    # 重定向回部门列表
    return redirect("/depart/list/")


def depart_multi(request):
    """ 文件上传(Excel) """

    # 获取上传的 Excel 文件对象
    file_object = request.FILES.get('exc')
    print(file_object)

    # 打开 Excel 文件读取内容
    wb = load_workbook(file_object)
    sheet = wb.worksheets[0]

    # 循环获取每一行数据,并更新至数据库
    for row in sheet.iter_rows(min_row=2):
        exc_title = row[0].value
        # 如果表格中的数据在数据库中不存在,则进行创建
        if not Department.objects.filter(title=exc_title).exists():
            Department.objects.create(title=exc_title)

    return HttpResponse("上传成功")

5.手动新建一个excel表格depart.xlsx,并输入以下内容。

image-20240319110917141

上传表格,选择文件后,点击上传。

image-20240319111006891

文件上传后,显示"上传成功",则结束上传。

image-20240319111038069

可以看到部门列表处新增了几个部门信息:

image-20240319111310393

值得注意的是,如果你上传了空字段,页面会报错,但不要担心,咱们只需要针对为空的特殊情况做下if判断处理下就能解决,实现了Excel文件上传。接下来我们一起利用之前所学的Form和ModelForm的知识,实现一下图片上传,但是可能到了这里,许多朋友已经有些许生疏,那先快速回顾一下Form和ModelForm:

3、Form和ModelForm回顾

首先需要明确的是,在Django框架中,FormModelForm都是用来处理表单数据的,但它们各有特点和用途:

1.Form

  • 定义: Form是Django中用于生成和处理HTML表单的一个基础工具。它定义了表单的结构、数据类型和验证方式,但与数据库模型(models)无直接关联。
  • 用途: 主要用于那些不直接与数据库模型对应的表单。例如,一个登录表单可能只需要用户名和密码字段,而不需要创建相应的数据库模型。
  • 特点:
    • 可以手动定义表单字段。
    • 包含数据验证功能,方便验证表单输入是否符合预期。
    • 通过创建forms.Form子类来使用。

2.ModelForm

  • 定义: ModelForm是Django中的一个特殊的Form类,它直接基于模型(Model)自动生成表单字段ModelForm会根据指定的模型自动创建表单字段,并且可以利用模型字段的定义来进行数据验证。
  • 用途: 主要用于需要与Django模型(数据库表)直接交互的场景。比如,当你需要创建或更新数据库记录时,ModelForm可以简化这一过程。
  • 特点:
    • 自动生成表单字段,字段类型和验证规则继承自对应的模型字段。
    • 简化了数据的保存过程,可以直接通过表单的save()方法保存或更新数据到数据库。
    • 通过创建forms.ModelForm子类并设置其Meta类的model属性为对应的Django模型来使用。

3.使用场景比较

  • 当你的表单数据需要直接与数据库交互(如创建、更新记录)时,使用ModelForm更方便,因为它减少了重复代码,并自动进行数据验证。
  • 如果你的表单不对应数据库中的模型,或者你需要一个完全自定义的表单行为,那么使用Form会更灵活。

4.示例

1️⃣Form 示例

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(label='Your name', max_length=100)
    message = forms.CharField(widget=forms.Textarea)

2️⃣ModelForm 示例

from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = ['name', 'email', 'message']

ModelForm的例子中,表单字段是基于Contact模型自动生成的,而在Form的例子中,每个字段都是手动定义的

回顾了以上内容后,我们对Form和ModelForm的记忆应该又浮出水面了,接下来让我们来逐一用它们来实现图片上传,首先是Form上传。

4、Form图片上传

1.在urls.py中上传列表的路径upload/form/,并告诉该路径指向的视图upload_from

urls.py

import chart as chart
from django.urls import path
from api.views import depart, user, pretty, admin, account, task, order, chart, upload

urlpatterns = [

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    path('depart/multi/', depart.depart_multi),
    path('upload/form/', upload.upload_form),
]

2.修改upload.py,在其中添加上传图片的类与视图。

upload.py

from django import forms
from django.shortcuts import render, HttpResponse
from api.utils.bootstrap import BootStrapForm


def upload_list(request):
    # GET方法主要用于获取信息,而POST方法则用于提交数据
    if request.method == "GET":
        return render(request, "upload_list.html")  # render函数负责将HTML模板渲染成最终的网页,并将这个网页返回给客户端。
    # 声明图片的对象
    file_object = request.FILES.get("avatar")

    # 分块进行存储
    # file_object.name 意思是图片上传前后保持原名称
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("上传成功")


class UpForm(BootStrapForm):
    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")


def upload_form(request):
    """上传图片"""
    title = "Form上传"
    form = UpForm()

    return render(request, 'upload_form.html', {"form": form, "title": title})

3.在templates目录下新建upload_form.html

upload_form.html

{% extends 'layout.html' %}

{% block content %}

<div class="container">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">{{ title }}</h3>
        </div>
        <div class="panel-body">
            <form method="post" enctype="multipart/form-data" novalidate>
                {% csrf_token %}

                {% for field in form %}
                    <div class="form-group">
                        <label>{{ field.label }}: </label>
                        {{ field }}
                        <!-- 数据校验,显示错误信息 -->
                        <span style="color: red;">{{ field.errors.0 }}</span>
                    </div>
                {% endfor %}

                <button type="submit" class="btn btn-primary">保存</button>
            </form>
        </div>
    </div>
</div>

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

效果:

image-20240319121607778

看到了上图实现的效果,但是这个框似乎有些不太妥当,因此我们对其做进一步的处理。

4.修改utils.py目录下的bootstrap.py

bootstrap.py

# -*- coding: utf-8 -*-            
# @Time : 2024-03-13 21:22
from django import forms

class BootStrapModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            # 字段中有属性,保留原来的属性,没有属性,才增加。
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
                    "class": "form-control",
                    "placeholder": field.label
                }

class BootStrapForm(forms.Form):

    bootstrap_exclude_fields = ['img']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            if name in self.bootstrap_exclude_fields:
                continue
            # 字段中有属性,保留原来的属性,没有属性,才增加
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
            else:
                field.widget.attrs = {
                    "class": "form-control",
                }

效果:

image-20240319122149485

到这里问题就解决了,接下来继续实现图片上传。

在 Django 的开发中一般要有两个特殊的文件夹:

  • static: 存放静态文件
  • media:存放用户上传的数据

static我们已然有了,但是media,我们还没有,需要进行一些配置。

5.修改urls.py,配置media路径。

urls.py

import chart as chart
from django.conf import settings
from django.urls import path, re_path
from django.views.static import serve

from api.views import depart, user, pretty, admin, account, task, order, chart, upload

urlpatterns = [
    # media配置
    re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    path('depart/multi/', depart.depart_multi),
    path('upload/form/', upload.upload_form),
]

6.修改settings.py,添加media根目录和路径

image-20240319123442899

MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

接下来实现

7.在api目录下新建media目录

image-20240319131843471

8.修改models.py,添加Boss数据表

models.py

class Boss(models.Model):
    """ Boss """
    name = models.CharField(verbose_name="姓名", max_length=32)
    age = models.IntegerField(verbose_name="年龄")
    img = models.CharField(verbose_name="头像", max_length=128)

之后进行数据库迁移,生成数据库表

python manage.py makemigrations
python manage.py migrate

image-20240319132209933

运行本地服务器,进行项目测试:

python manage.py runserver

image-20240319132220676

9.修改upload.py

upload.py

from django import forms
from django.shortcuts import render, HttpResponse

from api.models import Boss
from api.utils.bootstrap import BootStrapForm
import os

def upload_list(request):
    # GET方法主要用于获取信息,而POST方法则用于提交数据
    if request.method == "GET":
        return render(request, "upload_list.html")  # render函数负责将HTML模板渲染成最终的网页,并将这个网页返回给客户端。
    # 声明图片的对象
    file_object = request.FILES.get("avatar")

    # 分块进行存储
    # file_object.name 意思是图片上传前后保持原名称
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("上传成功")


class UpForm(BootStrapForm):
    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")


from django.conf import settings


def upload_form(request):
    """ 上传图片 """

    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {"form": form, "title": title})

    form = UpForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # {'name': '张三', 'age': 21, 'img': <InMemoryUploadedFile: code.png (image/png)>}
        # 1.读取图片内容,写入到文件夹中并获取文件的路径
        image_object = form.cleaned_data.get("img")
        # media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
        media_path = os.path.join('media', image_object.name)

        f = open(media_path, mode="wb")
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()

        # 2.将图片文件路径写入数据库
        Boss.objects.create(
            name=form.cleaned_data['name'],
            age=form.cleaned_data['age'],
            img=media_path,
        )

        return HttpResponse('ok')
    return render(request, 'upload_form.html', {"form": form, "title": title})

效果:

image-20240319132614881

image-20240319132610232

可以看到图片已经上传到咱们本地的media目录下了。

image-20240319132649241

同时咱们也可以查看数据表,可以看到信息也记录到了数据库里。

image-20240319132750199

到了这里Form上传图片就基本完成了,接下来咱们再一起尝试用ModelForm实现图片上传。

5、ModelForm图片上传(推荐)

1.数据准备,在models.py中创建一个"城市"数据表。

models.py

class City(models.Model):
    """ 城市 """
    name = models.CharField(verbose_name="城市", max_length=32)
    count = models.IntegerField(verbose_name="人口")
    img = models.FileField(verbose_name="Logo", max_length=128, upload_to='city/')

之后进行数据库迁移,生成数据库表

python manage.py makemigrations
python manage.py migrate

image-20240319133155233

运行本地服务器,进行项目测试:

python manage.py runserver

2.修改bootstrap.py

bootstrap.py

# -*- coding: utf-8 -*-
# @Time : 2024-03-13 21:22
from django import forms

class BootStrap:
    bootstrap_exclude_fields = []

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            if name in self.bootstrap_exclude_fields:
                continue
            # 字段中有属性,保留原来的属性,没有属性,才增加。
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {
                    "class": "form-control",
                    "placeholder": field.label
                }

class BootStrapModelForm(BootStrap, forms.ModelForm):
    pass

class BootStrapForm(forms.Form):

    bootstrap_exclude_fields = ['img']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段的插件设置
        for name, field in self.fields.items():
            if name in self.bootstrap_exclude_fields:
                continue
            # 字段中有属性,保留原来的属性,没有属性,才增加
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
            else:
                field.widget.attrs = {
                    "class": "form-control",
                }

3.修改upload.py

upload.py

from django import forms
from django.shortcuts import render, HttpResponse

from api.models import Boss, City
from api.utils.bootstrap import BootStrapForm, BootStrapModelForm
import os

def upload_list(request):
    # GET方法主要用于获取信息,而POST方法则用于提交数据
    if request.method == "GET":
        return render(request, "upload_list.html")  # render函数负责将HTML模板渲染成最终的网页,并将这个网页返回给客户端。
    # 声明图片的对象
    file_object = request.FILES.get("avatar")

    # 分块进行存储
    # file_object.name 意思是图片上传前后保持原名称
    f = open(file_object.name, mode='wb')
    for chunk in file_object.chunks():
        f.write(chunk)
    f.close()

    return HttpResponse("上传成功")


class UpForm(BootStrapForm):
    name = forms.CharField(label="姓名")
    age = forms.IntegerField(label="年龄")
    img = forms.FileField(label="头像")


from django.conf import settings


def upload_form(request):
    """ 上传图片 """

    title = "Form上传"
    if request.method == "GET":
        form = UpForm()
        return render(request, 'upload_form.html', {"form": form, "title": title})

    form = UpForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # {'name': '张三', 'age': 21, 'img': <InMemoryUploadedFile: code.png (image/png)>}
        # 1.读取图片内容,写入到文件夹中并获取文件的路径
        image_object = form.cleaned_data.get("img")
        # media_path = os.path.join(settings.MEDIA_ROOT, image_object.name)
        media_path = os.path.join('media', image_object.name)

        f = open(media_path, mode="wb")
        for chunk in image_object.chunks():
            f.write(chunk)
        f.close()

        # 2.将图片文件路径写入数据库
        Boss.objects.create(
            name=form.cleaned_data['name'],
            age=form.cleaned_data['age'],
            img=media_path,
        )

        return HttpResponse('ok')
    return render(request, 'upload_form.html', {"form": form, "title": title})


class UpModelForm(BootStrapModelForm):

    bootstrap_exclude_fields = ['img']

    class Meta:
        model = City
        fields = "__all__"

def upload_model_form(request):
    """ 上传文件和数据 """
    title = "ModelForm上传文件"
    if request.method == "GET":
        form = UpModelForm()
        return render(request, 'upload_form.html', {"form": form, "title": title})

    form = UpModelForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 对于文件会自动保存
        # 目录信息会自动保存至数据库中
        form.save()

        return HttpResponse("success!")
    return render(request, 'upload_form.html', {"form": form, "title": title})

4.修改urls.py,添加图片上传列表的路径upload/model/form/,并告诉该路径指向的视图upload_model_form

import chart as chart
from django.conf import settings
from django.urls import path, re_path
from django.views.static import serve

from api.views import depart, user, pretty, admin, account, task, order, chart, upload

urlpatterns = [
    # media配置
    re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    path('depart/multi/', depart.depart_multi),
    path('upload/form/', upload.upload_form),
    path('upload/model/form/', upload.upload_model_form),
]

5.修改layout.html

image-20240319134846915

layout.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--Bootstrap框架-->
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'plugins/font-awesome-4.7.0/css/font-awesome.css' %}">

    <!--datetimepicker插件-->
    <link rel="stylesheet" type="text/css"
          href="{% static 'plugins/bootstrap-datetimepicker/css/bootstrap-datetimepicker.css' %}">
    {% block css %}
        <style>
            .navbar {
                border-radius: 0;
            }
        </style>
    {% endblock %}
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container">

        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">用户管理系统</a>
        </div>

        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/admin/list">管理员账户</a></li>
                <li><a href="/depart/list">部门管理</a></li>
                <li><a href="/user/list">用户管理</a></li>
                <li><a href="/pretty/list">靓号管理</a></li>
                <li><a href="/task/list">任务管理</a></li>
                <li><a href="/order/list">订单管理</a></li>
                <li><a href="/chart/list">数据统计</a></li>
                <li><a href="/upload/list/">上传文件</a></li>
            </ul>
            <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="/upload/list/">上传图片</a></li>
                        <li><a href="/upload/form/">Form上传图片</a></li>
                        <li><a href="/upload/model/form/">ModelForm上传图片</a></li>
                    </ul>
                </li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="/login">登录</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">{{ request.session.info.name }}<span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">个人资料</a></li>
                        <li><a href="#">我的信息</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="/logout/">注销</a></li>
                    </ul>
                </li>

            </ul>
        </div>
    </div>
</nav>

<div>
    <div class="container">
        {% block content %}{% endblock %}
    </div>
</div>

<script src="{% static 'js/jquery.min.js' %}"></script>
<!-- 加载 Bootstrap DateTimePicker JS -->
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.js' %}"></script>
<script src="{% static 'plugins/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js' %}"></script>

<script type="text/javascript">
    $(function () {
        //当容器加载完成,对容器调用工具函数
        $("#dt").datetimepicker({
            language: 'zh-CN', //语言
            format: 'yyyy-mm-dd',//日期的格式
            minView: 'month', //可以选择的最小视图
            initialDate: new Date(),//初始化显示的日期
            autoclose: true,//设置选择完日期或者时间之后,日否自动关闭日历
            todayBtn: true,//设置自动显示为今天
            clearBtn: false//设置是否清空按钮,默认为false
        });
    });
</script>
{% block js %}
{% endblock %}

效果:

image-20240319135438705

image-20240319135553303

浏览器进行响应:

image-20240319135545030

查看media目录,可以看到创建了city目录,并上传了图片。

image-20240319135632334

可以看到数据库中也存储了相应信息。

image-20240319135719579

上面的内容,咱们已经学会了如何实现上传文件,但是没有具体的案例实践,掌握还是比较难的,因此咱们举一个简单的例子来应用一下咱们上述所学。

6、城市管理

1.修改urls.py,添加城市管理列表的路径city/list/和city/add/,并告诉该路径指向的视图city_list与city_add

urls.py

import chart as chart
from django.conf import settings
from django.urls import path, re_path
from django.views.static import serve

from api.views import depart, user, pretty, admin, account, task, order, chart, upload

urlpatterns = [
    # media配置
    re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),

    # 部门管理
    path("depart/list/", depart.depart_list),
    path("depart/add/", depart.depart_add),
    path("depart/delete/", depart.depart_delete),
    path("depart/<int:nid>/edit/", depart.depart_edit),

    # 用户管理
    path("user/list/", user.user_list),
    path("user/add/", user.user_add),
    path("user/model/form/add/", user.user_model_form_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path("user/<int:nid>/delete/", user.user_delete),

    # 靓号管理
    path("pretty/list/", pretty.pretty_list),
    path("pretty/add/", pretty.pretty_add),
    path("pretty/<int:nid>/edit/", pretty.pretty_edit),
    path("pretty/<int:nid>/delete/", pretty.pretty_delete),

    # 管理员管理
    path('admin/list/', admin.admin_list),
    path('admin/add/', admin.admin_add),
    path('admin/<int:nid>/edit/', admin.admin_edit),
    path('admin/<int:nid>/delete/', admin.admin_delete),
    path('admin/<int:nid>/reset/', admin.admin_reset),

    # 用户登录
    path('login/', account.login),
    path('logout/', account.logout),
    path('image/code/', account.image_code),

    # 任务管理
    path('task/list/', task.task_list),
    path('task/ajax/', task.task_ajax),
    path('task/add/', task.task_add),

    # 订单管理
    path('order/list/', order.order_list),
    path('order/add/', order.order_add),
    path('order/delete/', order.order_delete),
    path('order/detail/', order.order_detail),
    path('order/edit/', order.order_edit),

    # 数据统计
    path('chart/list/', chart.chart_list),
    path('chart/bar/', chart.chart_bar),
    path('chart/pie/', chart.chart_pie),
    path('chart/line/', chart.chart_line),

    # 文件上传
    path('upload/list/', upload.upload_list),
    path('depart/multi/', depart.depart_multi),
    path('upload/form/', upload.upload_form),
    path('upload/model/form/', upload.upload_model_form),

    # 城市管理
    path('city/list/', city.city_list),
    path('city/add/', city.city_add),
]

2.在views目录下新建city.py

city.py

from api.utils.bootstrap import BootStrapModelForm
from django.shortcuts import render, redirect
from api.models import City
from api.utils.pagination import Pagination


def city_list(request):
    """ 城市列表 """
    data_dict = {}
    # 如果是空字典,表示获取所有
    # 不加后面的 "", 首次访问浏览器,搜索框中不会显示前端页面中的 placeholder="Search for..." 属性
    search_data = request.GET.get('query', "")
    if search_data:
        data_dict["name__contains"] = search_data

    queryset = City.objects.filter(**data_dict).order_by("-count")

    ### 引入封装的 Pagination 类并初始化
    # 初始化
    page_object = Pagination(request, queryset, page_size=10, page_param="page")
    page_queryset = page_object.page_queryset

    # 调用对象的html方法,生成页码
    page_object.html()

    page_string = page_object.page_string

    context = {
        "page_queryset": page_queryset,  # 分页的数据
        "search_data": search_data,  # 搜索的内容
        "page_string": page_string,  # 页码
    }

    return render(request, 'city_list.html', context)


class UpModelForm(BootStrapModelForm):
    bootstrap_exclude_fields = ['img']

    class Meta:
        model = City
        fields = "__all__"


def city_add(request):
    """ 新建城市 """
    if request.method == "GET":
        form = UpModelForm()
        return render(request, 'upload_form.html', {"form": form})

    form = UpModelForm(data=request.POST, files=request.FILES)
    if form.is_valid():
        # 对于文件会自动保存
        # 目录信息会自动保存至数据库中
        form.save()

        return redirect('/city/list/')
    return render(request, 'upload_form.html', {"form": form})

3.在templates目录下新建city_list.html

city_list.html

{% extends 'layout.html' %}

{% block content %}
<div class="container">
    <div style="margin-bottom: 10px">
        <a class="btn btn-primary" href="/city/add/" target="_blank">新建城市</a>

        <div style="float: right; width: 300px;">
            <form method="get">
                <div class="input-group">
                    <input type="text" name="query" class="form-control" placeholder="Search for..."
                        value="{{ search_data }}">
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">
                            <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                        </button>
                    </span>
                </div>
            </form>
        </div>
    </div>


    <div>
        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span>
                <span>部门列表</span>
            </div>

            <!-- Table -->
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Logo</th>
                        <th>名称</th>
                        <th>人口</th>
                    </tr>
                </thead>
                <tbody>
                    {% for obj in page_queryset %}
                    <tr>
                        <th>{{ obj.id }}</th>
                        <td>
                            <img src="/media/{{ obj.img }}" style="height: 60px;">
                        </td>
                        <td>{{ obj.name }}</td>
                        <td>{{ obj.count }}</td>
                    </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
    <ul class="pagination">
        {{ page_string }}
    </ul>
</div>

{% endblock %}

4.修改layout.html,加入城市管理列表。

image-20240319143410552

<li><a href="/city/list/">城市管理</a></li>

效果:

image-20240319144700249

142

系统整体效果:

143

至此Python Web开发的内容就到此落下帷幕了,以上实现的系统,界面或许比较简单,但是基本覆盖了常用的各类功能,以后在此思路之上进行拓展,系统会更加完善。前方道路漫漫,这只是短暂的旅程,未来尚有许多前景,加油!

很感谢你能看到这里,如有相关疑问,还请下方评论留言。
Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
希望本篇内容能对大家有所帮助,如果大家喜欢的话,请动动手点个赞和关注吧,非常感谢你们的支持!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matlab DDPG

文章目录 1 rlSimulinkEnv1.1 说明1.2 例子1.2.1 使用工作空间Agent创建Simulink环境1.2.2 为Simulink模型创建强化学习环境1.2.3 创建Simulink多Agents环境2 创建Simulink环境和训练Agent2.1 创建环境接口2.2 创建DDPG Agent2.3 训练Agent2.4 验证已训练的Agent3 创建Simulink…

opengl日记7-ubuntu20.04开发环境opengl拓展glfw和glad环境搭建

文章目录 ubuntu中安装opengl核心环境安装glfw安装glad测试验证程序vscode的task.json配置如下note参考 ubuntu中安装opengl核心环境 可执行如下命令进行整体安装&#xff1a; sudo apt-get install libgl1-mesa-dev*或者单独安装 1、提供编译程序必须软件包的列表信息 sud…

【NLP笔记】Transformer

文章目录 基本架构EmbeddingEncoderself-attentionMulti-Attention残差连接LayerNorm DecoderMask&Cross Attention线性层&softmax损失函数 论文链接&#xff1a; Attention Is All You Need 参考文章&#xff1a; 【NLP】《Attention Is All You Need》的阅读笔记 一…

智慧城市的发展趋势与挑战:未来展望

随着信息技术的飞速发展&#xff0c;智慧城市已成为现代城市发展的重要方向。智慧城市通过集成应用先进的信息通信技术&#xff0c;实现城市管理、服务、运行的智能化&#xff0c;为城市的可持续发展注入了新的活力。然而&#xff0c;在智慧城市的发展过程中&#xff0c;也面临…

自动化改变金融科技文档生命周期

金融科技公司可能处于软件开发的最前沿&#xff0c;但即使是最先进的系统也必须能够支持金融服务领域采用的一系列文档密集型程序。因此&#xff0c;绝大多数金融科技企业都使用数字文档管理解决方案&#xff0c;无论是内部构建的还是由第三方供应商开发的。金融科技公司可以通…

3D开发工具HOOPS如何助力3D项目实现扩展现实技术?

在当今数字化时代&#xff0c;扩展现实&#xff08;Augmented Reality&#xff0c;AR&#xff09;技术的应用已经逐渐深入到各行各业&#xff0c;为用户带来了前所未有的沉浸式体验。而在实现这种技术的开发过程中&#xff0c;HOOPS技术的运用无疑是一种强大的助力。HOOPS是一种…

项目构建流程

项目构建 目录结构 引入application.properties admin模块就用9090端口 api 模块就用9091端口&#xff0c;其他配置先一样 # 应用服务 WEB 访问端口 server.port9090 server.servlet.context-path/api #session过期时间 60M 一个小时 server.servlet.session.timeoutPT60M #…

Pytorch DataLoader 提高模型训练时的 Volatile Gpu-Util(GPU利用率)

文章目录 1. 查看GPU显存占比和利用率2. Pytorch 提高 GPU 利用率的方法 1. 查看GPU显存占比和利用率 watch -n 0.2 nvidia-smi0.2 代表每隔 0.2 秒刷新一次 GPU 使用情况 通过调整 batch_size 可以使 Memory-Usage&#xff08;GPU显存占比&#xff09;尽可能高&#xff1b;但…

【联邦学习Fate架构讲解】

1.联邦学习的网络架构 P2P网络 网络中的每个成员建议通信 Star网络 网络中的每个成员只需要和中心的exchange交换信息 2. FATE中的架构 2.1 EggRoll分布式计算和存储 Egg Roll分布式计算和存储 存储部分 storage service计算部分 processor管理 egg manager 2.2 FateBoard联…

如何解决node-sass下载用的还是过期的淘宝源?

下载node-sass发现报错过期的证书 把npm的淘宝源换成最新的https://registry.npmmirror.com后发现还是指向了以前的淘宝源&#xff0c;看到一位博主说&#xff0c;单改npm源不够还要改下载node-sass的源&#xff0c;再次搜索另外一位博主提供了命令npm config ls可以使用它来查…

[GPT概念-02] — 预训练、微调和不同的用例应用

GPT: Generative Pretrained Transformer 一、说明 在之前的博客中&#xff0c;我们研究了生成式预训练转换器的整个概述。现在让我们看看关于预训练、微调和不同用例应用的超级重要主题。 二、预备训练 预训练是关于在没有监督或显式监督的情况下&#xff0c;我们从大型未标记…

WPF按钮相关

跟着官网敲的按钮相关的内容,还涉及了wpf很多其他的知识 1.创建基本按钮 <Grid><StackPanel HorizontalAlignment"Left"><Button>Button1</Button><Button>Button2</Button><Button>Button3</Button></StackPan…

开源模型应用落地-安全合规篇-模型输出合规性检测(三)

一、前言 为什么我们需要花大力气对用户输入的内容和模型生成的输出进行合规性检测,一方面是严格遵守各项法规要求,具体如下:互联网信息服务深度合成管理规定https://www.gov.cn/zhengce/zhengceku/2022-12/12/content_5731431.htm ​ 其次,受限于模型本身的一些缺陷,…

目标检测——PP-YOLO算法解读

PP-YOLO系列&#xff0c;均是基于百度自研PaddlePaddle深度学习框架发布的算法&#xff0c;2020年基于YOLOv3改进发布PP-YOLO&#xff0c;2021年发布PP-YOLOv2和移动端检测算法PP-PicoDet&#xff0c;2022年发布PP-YOLOE和PP-YOLOE-R。由于均是一个系列&#xff0c;所以放一起解…

大数据技术学习笔记(十三)—— HBase

目录 1 Hbase 概述1.1 Hbase 定义1.2 HBase 数据模型1.2.1 HBase 逻辑结构1.2.2 HBase 物理存储结构1.2.3 数据模型 1.3 HBase 基本架构 2 HBase Shell 操作2.1 基本操作2.2 namespace 操作2.3 表操作 3 HBase 原理深入3.1 RegionServer 架构3.2 HBase 写流程3.3 MemStore Flus…

华为中心AP 配置入侵防御实验

配置入侵防御示例 组网图形 图1 入侵防御组网图 组网需求配置思路操作步骤中心AP的配置文件 组网需求 如图1所示&#xff0c;某企业部署了WLAN网络&#xff0c;内网用户可以访问Internet的Web服务器。现需要在中心AP上配置入侵防御功能&#xff0c;具体要求如下&#xff1a; 保…

python基于django的高校迎新系统 flask新生报到系统

系统的登录界面和业务逻辑简洁明了&#xff0c;采用一般的界面窗口来登录界面,整个系统更加人性化&#xff0c;用户操作更加简洁方便。本系统在操作和管理上比较容易&#xff0c;还具有很好的交互性等特点&#xff0c;在操作上是非常简单的。因此&#xff0c;本系统可以进行设计…

基础知识(读取指定数据/布尔索引/nan/inf)

读取数据 代码 import numpy as np# 文件的路径 us_file_path"./youtube_video_data/US_video_data_numbers.csv" uk_file_path"./youtube_video_data/GB_video_data_numbers.csv"# 读取文件 t1np.loadtxt(us_file_path,delimiter,,dtypeint) t2np.loadt…

【2024.3.19练习】统计子矩阵

题目描述 题目分析 这道题一开始没有思路&#xff0c;使用蛮力枚举的方法时间复杂度为&#xff0c;显然超时。 参考题解后学会了化二维问题为一维问题&#xff0c;先使用的复杂度限制子矩阵的高度&#xff0c;再考虑列&#xff0c;这样就将子矩阵的和问题转变为了连续子序列的…

本地gitlab-runner的创建与注册

引言 之前通过一些方式在本地创建runner&#xff0c;时而会出现一些未知的坑&#xff0c;所以写下本文记录runner可以无坑创建的方式。 以下注册runner到相应仓库的前提是已经在本地安装了gitlab-runner 具体安装方式见官网 本地gitlab-runner安装常用的指令 查看gitlab r…