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

2024-03-19 19:04

本文主要是介绍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, charturlpatterns = [# 部门管理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, HttpResponsedef 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, uploadurlpatterns = [# 部门管理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_workbookdef 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=1nid = 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 formsclass 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 Contactclass ContactForm(forms.ModelForm):class Meta:model = Contactfields = ['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, uploadurlpatterns = [# 部门管理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 BootStrapFormdef 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 formsclass 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.labelelse: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 servefrom api.views import depart, user, pretty, admin, account, task, order, chart, uploadurlpatterns = [# 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, HttpResponsefrom api.models import Boss
from api.utils.bootstrap import BootStrapForm
import osdef 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 settingsdef 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 formsclass 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.labelelse:field.widget.attrs = {"class": "form-control","placeholder": field.label}class BootStrapModelForm(BootStrap, forms.ModelForm):passclass 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, HttpResponsefrom api.models import Boss, City
from api.utils.bootstrap import BootStrapForm, BootStrapModelForm
import osdef 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 settingsdef 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 = Cityfields = "__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 servefrom api.views import depart, user, pretty, admin, account, task, order, chart, uploadurlpatterns = [# 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 servefrom api.views import depart, user, pretty, admin, account, task, order, chart, uploadurlpatterns = [# 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 Paginationdef city_list(request):""" 城市列表 """data_dict = {}# 如果是空字典,表示获取所有# 不加后面的 "", 首次访问浏览器,搜索框中不会显示前端页面中的 placeholder="Search for..." 属性search_data = request.GET.get('query', "")if search_data:data_dict["name__contains"] = search_dataqueryset = 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_stringcontext = {"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 = Cityfields = "__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😊)
希望本篇内容能对大家有所帮助,如果大家喜欢的话,请动动手点个赞和关注吧,非常感谢你们的支持!

这篇关于Python Web开发记录 Day16:Django part10 文件上传(完结篇)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/826973

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)