名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪)
创作者:Code_流苏(****)(一个喜欢古诗词和编程的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。
在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 %}
上传文件
浏览器进行响应
此时就能发现,文件夹下多了一张咱们上传的图片。
基础的文件上传操作,咱们了解之后,之后来实现一下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
补充: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,并输入以下内容。
上传表格,选择文件后,点击上传。
文件上传后,显示"上传成功",则结束上传。
可以看到部门列表处新增了几个部门信息:
值得注意的是,如果你上传了空字段,页面会报错,但不要担心,咱们只需要针对为空的特殊情况做下if判断处理下就能解决,实现了Excel文件上传。接下来我们一起利用之前所学的Form和ModelForm的知识,实现一下图片上传,但是可能到了这里,许多朋友已经有些许生疏,那先快速回顾一下Form和ModelForm:
3、Form和ModelForm回顾
首先需要明确的是,在Django框架中,Form
和ModelForm
都是用来处理表单数据的,但它们各有特点和用途:
1.Form
-
定义:
Form
是Django中用于生成和处理HTML表单的一个基础工具。它定义了表单的结构、数据类型和验证方式,但与数据库模型(models)无直接关联。 - 用途: 主要用于那些不直接与数据库模型对应的表单。例如,一个登录表单可能只需要用户名和密码字段,而不需要创建相应的数据库模型。
-
特点:
- 可以手动定义表单字段。
- 包含数据验证功能,方便验证表单输入是否符合预期。
- 通过创建
forms.Form
子类来使用。
2.ModelForm
-
定义:
ModelForm
是Django中的一个特殊的Form类,它直接基于模型(Model)自动生成表单字段。ModelForm