文件上传
简单的文件上传
# 前端\django\myweb\blog\views\upload.py
from django.shortcuts import render
# 文件上传
def upload_list(request):
if request.method == "GET":
return render(request, 'upload_list.html')
# print(request.POST)
# 请求体中的数据 <QueryDict: {'csrfmiddlewaretoken': ['a1XA483cVlBrDSjxKUmKFuceHVH1xK71zcN5RkMOi2O3s3QsYY2ZXRJUc4c5rtxd'], 'username': ['123'], 'avatar': ['haha.png']}> 只有文件名
# print(request.FILES) # 请求发过来的文件 <MultiValueDict: {}>
# form enctype="multipart/form-data" 标签增加<form method="post" enctype="multipart/form-data">
# print(request.POST) # <QueryDict: {'csrfmiddlewaretoken': ['vajr76cDl985ap69GUW2puOdyRDRgIOJUl9WUiVfIQlHZAD4UYChHRlT308VareV'], 'username': ['123']}>
# print(request.FILES) # 请求发过来的文件 <MultiValueDict: {'avatar': [<InMemoryUploadedFile: haha.png (image/png)>]}>
file_obj = request.FILES.get("avatar")
# print(file_obj.name) # haha.png
# with open('blog/static/img/haha2.png', mode="wb") as f:
with open(f'blog/static/img/{file_obj.name}', mode="wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
# 前端\django\myweb\haha2.png 默认保存在项目根目录
return HttpResponse("haha")
<!-- 前端\django\myweb\blog\templates\upload_list.html -->
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="username">
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
</div>
{% endblock %}
批量上传案例-普通
excel 处理: pip install openpyxl
<!-- 前端\django\myweb\blog\templates\pretty_list.html -->
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<a href="/pretty/add/">
<button class="btn btn-success"><span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
新增靓号-ModelForm</button>
</a>
</div>
</div>
<div class="col-lg-6">
<form method="get" action="/pretty/list/">
<div class="input-group">
<input type="text" class="form-control" placeholder="查询手机号" name="q" value="{{ search_data }}">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit"><span class="glyphicon glyphicon-search"
aria-hidden="true"></span><strong> 搜索</strong></button>
</span>
</div>
</form>
</div>
</div>
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> 普通上传案例
</strong>
</div>
<div class="panel-body">
<form method="post" enctype="multipart/form-data" action="/pretty/upload/">
{% csrf_token %}
<input type="file" name="pretty_excel">
<br>
<input type="submit" value="Form 上传" class="btn btn-primary">
</form>
</div>
</div>
<div style="margin-top: 20px;">
<div class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 靓号列表
</strong>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>手机号码</th>
<th>价格</th>
<th>等级</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for iteam in pretty_list %}
<tr>
<th scope="row">{{ iteam.id }}</th>
<td>{{ iteam.mobile }}</td>
<td>{{ iteam.price }}</td>
<td>{{ iteam.get_level_display }}</td>
<td>{{ iteam.get_status_display }}</td>
<td>
<a class="btn btn-primary btn-xs" href="/pretty/{{ iteam.id }}/edit/"> 编辑 </a>
<a class="btn btn-danger btn-xs" href="/pretty/{{ iteam.id }}/del/"> 删除 </a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<nav aria-label="page">
<ul class="pagination">
{{ page_string }}
<form method="get" action="/pretty/list/">
<div class="input-group col-sm-2" style="display: inline-block;margin-left: 20px;">
<span class="input-group-btn">
<input type="text" class="form-control" placeholder="页面跳转" name="page">
<button class="btn btn-primary" type="submit">>> 跳转</button>
</span>
</div>
</form>
</ul>
</nav>
</div>
{% endblock %}
# 前端\django\myweb\blog\views\pretty.py
# pretty_upload函数
def pretty_upload(request):
# 获取用户上传的文件对象 # 前端\django\myweb\blog\static\img\test.xlsx
file_obj = request.FILES.get("pretty_excel")
# print(type(file_obj)) # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
# from django.core.files.uploadedfile import InMemoryUploadedFile # 查看对象原码内容
# 对象传递给 openpyxl,由openpyxl 读取文件的内容
# import os
from openpyxl import load_workbook
# file_path = os.path.join('files', 'test.xlsx')
# work_book_obj = load_workbook(file_path)
work_book_obj = load_workbook(file_obj)
sheet_list = work_book_obj.sheetnames # 获取所有sheet的名字
# print(sheet_list) # ['Sheet1']
sheet = work_book_obj.worksheets[0]
# print(type(sheet)) # <class 'openpyxl.worksheet.worksheet.Worksheet'>
# print(sheet) # <Worksheet "Sheet1">
# 读取表格内容
# cell = sheet.cell(1, 1) # 读取第一行第一列
# print(cell) # <Cell 'Sheet1'.A1>
# print(cell.value) # 手机号码
# 循环获取第一行数据
# sheet.rows # 每一行
for row in sheet.iter_rows(min_row=2): # 第一行是标题,从第二行开始取数据
# print(row) # (<Cell 'Sheet1'.A2>, <Cell 'Sheet1'.B2>, <Cell 'Sheet1'.C2>, <Cell 'Sheet1'.D2>) ......
# print(row[0].value, row[1].value, row[2].value, row[3].value) # 15388868690 88888690 1 2 ......
row_dict = {
"mobile": row[0].value,
"price": row[1].value,
"level": row[2].value,
"status": row[3].value
}
exists = PrettyNum.objects.filter(**row_dict).exists()
if not exists:
PrettyNum.objects.create(**row_dict)
return redirect("/pretty/list/")
文件上传插件Bootstrap File Input
Bootstrap文件上传插件File Input: https://plugins.krajee.com/file-input
# bootstrap file input 插件上传
@csrf_exempt
def upload_fileinput(request):
file_obj = request.FILES.get("input-b1")
# print(file_obj.name)
with open(f'blog/static/img/{file_obj.name}', mode="wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
return JsonResponse({"status": True})
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Bootstrap File Input 插件案例
</strong>
</div>
<div class="panel-body file-loading">
<input id="input-b1" name="input-b1" type="file" data-show-preview="true" multiple>
</div>
</div>
{% block js %}
{% load static %}
<script src="{% static 'plugins/bootstrap-fileinput-5.5.4/js/fileinput.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-fileinput-5.5.4/js/locales/zh.js' %}"></script>
{% endblock %}
{% block script %}
<script>
$(document).ready(function () {
$("#input-b1").fileinput({
uploadUrl: "/upload/fileinput/",
maxFileCount: 5
});
});
</script>
{% endblock %}
混合数据案例-Form方法
# 前端\django\myweb\blog\utils\modelform.py
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["style"] = "width: 300px;"
if "placeholder" in field.widget.attrs:
continue
else:
field.widget.attrs["placeholder"] = field.label
else:
field.widget.attrs = {
"class": "form-control",
"style": "width: 300px;",
"placeholder": field.label
}
class BootStrapForm(BootStrap, forms.Form):
pass
# 前端\django\myweb\blog\utils\form.py
# Form 文件上传
class UploadForm(BootStrapForm):
bootstrap_exclude_fields = ["img"]
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
# 前端\django\myweb\blog\views\upload.py
# Form上传案例
def upload_form(request):
form = UploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
# print(form.cleaned_data) # {'name': 'tang', 'age': 18, 'img': <InMemoryUploadedFile: haha.png (image/png)>}
# 读取图片内容,写入到文件夹中并获取文件的路径
image_obj = form.cleaned_data.get('img')
file_path = f'blog/static/img/{image_obj.name}'
with open(file_path, mode="wb") as f:
for chunk in image_obj.chunks():
f.write(chunk)
# 装图片文件路径写入到数据库
db_file_path = f'/static/img/{image_obj.name}'
Boss.objects.create(
name=form.cleaned_data['name'],
age=form.cleaned_data['age'],
img=db_file_path
)
return redirect(db_file_path)
return render(request, 'upload_list.html', {"form": form})
<!-- 前端\django\myweb\blog\templates\upload_list.html -->
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Form 上传案例
</strong>
</div>
<div class="panel-body">
<form method="post" enctype="multipart/form-data" action="/upload/form/" 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 %}
<div class="form-group" style="margin-top: 20px;">
<button type="submit" class="btn btn-primary">Form 上传案例</button>
</div>
</form>
</div>
</div>
Django开过程中两个特殊的文件夹
- static 存放静态文件的路径,包括:css,js,项目图片
- media 用户上传的数据
启用media
在urls.py中进行配置 前端\django\myweb\myweb\urls.py
from django.urls import path, re_path
from django.conf import settings
from django.views.static import serve
urlpatterns = [
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}, name='media'),
]
# 前端\django\myweb\myweb\settings.py
import os
# 启用media
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = '/media/'
混合数据案例-ModelForm方法-完整代码
<!-- # 前端\django\myweb\blog\templates\upload_list.html -->
{% extends 'layout.html' %}
{% block css %}
{% load static %}
<link rel="stylesheet" href="{% static 'plugins/bootstrap-fileinput-5.5.4/css/fileinput.min.css' %}">
<link rel="stylesheet" href="{% static 'plugins/icons-1.5.0/font/bootstrap-icons.min.css' %}">
{% endblock %}
{% block content %}
<div class="container">
<div>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="username">
<input type="file" name="avatar">
<input type="submit" value="提交">
</form>
</div>
<br>
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Bootstrap File Input 插件案例
</strong>
</div>
<div class="panel-body file-loading">
<input id="input-b1" name="input-b1" type="file" data-show-preview="true" multiple>
<input readonly="" class="file-caption-name form-control kv-fileinput-caption" placeholder="Select files ..." title="">
</div>
</div>
<br>
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> Form 上传案例-Boss
</strong>
</div>
<div class="panel-body">
<form method="post" enctype="multipart/form-data" action="/upload/form/" 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 %}
<div class="form-group" style="margin-top: 20px;">
<button type="submit" class="btn btn-primary">Form 上传案例-Boss</button>
</div>
</form>
</div>
</div>
<!-- 新建/编辑-对话框 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h3 class="modal-title" id="myModalLabel">ModelForm 上传案例-City</h3>
</div>
<div class="modal-body">
<form id="formModal" class="form-group" method="post" enctype="multipart/form-data"
action="/upload/modelform/" novalidate>
{% csrf_token %}
{% for field in modelform %}
<div class="form-group">
<label>{{ field.label }}</label>
{{ field }}
<span style="color: red;">{{ field.errors.0 }}</span>
</div>
{% endfor %}
<div class="form-group" style="margin-top: 20px;">
<button type="submit" class="btn btn-primary">ModelForm 上传案例-City</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div style="margin-top: 20px;" class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> ModelForm 上传案例-City
</strong>
</div>
<div class="panel-body">
<div class="form-group" style="margin-top: 20px;">
<input type="button" value="ModelForm 上传案例" class="btn btn-primary" data-toggle="modal"
data-target="#myModal">
</div>
</div>
</div>
<div style="margin-top: 20px;">
<div class="panel panel-default">
<div class="panel-heading">
<strong>
<span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 城市列表
</strong>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>城市</th>
<th>人口</th>
<th>LOGO</th>
</tr>
</thead>
<tbody>
{% for iteam in city_list %}
<tr>
<th scope="row">{{ iteam.id }}</th>
<td>{{ iteam.name }}</td>
<td>{{ iteam.count }}</td>
<td><img src="/media/{{ iteam.img }}" style="height: 80px;" alt=""></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
{% block js %}
{% load static %}
<script src="{% static 'plugins/bootstrap-fileinput-5.5.4/js/fileinput.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-fileinput-5.5.4/js/locales/zh.js' %}"></script>
{% endblock %}
{% block script %}
<script>
$(document).ready(function () {
$("#input-b1").fileinput({
language: "zh",
uploadUrl: "/upload/fileinput/",
maxFileCount: 5,
allowedFileExtensions: ["jpg", "png", "gif"]
});
});
</script>
{% endblock %}
# 前端\django\myweb\blog\views\upload.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from blog.utils.form import UploadForm, UploadModelForm
from blog.models import Boss,City
from django.conf import settings
# 文件上传
def upload_list(request):
if request.method == "GET":
form = UploadForm()
modelform = UploadModelForm()
city_list = City.objects.all().order_by('-id')
return render(request, 'upload_list.html', {"form": form, "modelform": modelform, "city_list": city_list})
# print(request.POST)
# 请求体中的数据 <QueryDict: {'csrfmiddlewaretoken': ['a1XA483cVlBrDSjxKUmKFuceHVH1xK71zcN5RkMOi2O3s3QsYY2ZXRJUc4c5rtxd'], 'username': ['123'], 'avatar': ['haha.png']}> 只有文件名
# print(request.FILES) # 请求发过来的文件 <MultiValueDict: {}>
# form enctype="multipart/form-data" 标签增加<form method="post" enctype="multipart/form-data">
# print(request.POST) # <QueryDict: {'csrfmiddlewaretoken': ['vajr76cDl985ap69GUW2puOdyRDRgIOJUl9WUiVfIQlHZAD4UYChHRlT308VareV'], 'username': ['123']}>
# print(request.FILES) # 请求发过来的文件 <MultiValueDict: {'avatar': [<InMemoryUploadedFile: haha.png (image/png)>]}>
file_obj = request.FILES.get("avatar")
# print(file_obj.name) # haha.png
# with open('blog/static/img/haha2.png', mode="wb") as f:
with open(f'blog/static/img/{file_obj.name}', mode="wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
# 前端\django\myweb\haha2.png 默认保存在项目根目录
return HttpResponse("haha")
# bootstrap file input 插件上传
@csrf_exempt
def upload_fileinput(request):
file_obj = request.FILES.get("input-b1")
# print(file_obj.name)
with open(f'blog/static/img/{file_obj.name}', mode="wb") as f:
for chunk in file_obj.chunks():
f.write(chunk)
return JsonResponse({"status": True})
# Form上传案例
def upload_form(request):
form = UploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
# print(form.cleaned_data) # {'name': 'tang', 'age': 18, 'img': <InMemoryUploadedFile: haha.png (image/png)>}
# 读取图片内容,写入到文件夹中并获取文件的路径
image_obj = form.cleaned_data.get('img')
file_path = f'blog/static/img/{image_obj.name}'
with open(file_path, mode="wb") as f:
for chunk in image_obj.chunks():
f.write(chunk)
# 装图片文件路径写入到数据库
db_file_path = f'/static/img/{image_obj.name}'
Boss.objects.create(
name=form.cleaned_data['name'],
age=form.cleaned_data['age'],
img=db_file_path
)
# print(settings.MEDIA_ROOT)
return redirect(db_file_path)
return render(request, 'upload_list.html', {"form": form})
# ModelForm上传案例
def upload_modelform(request):
modelform = UploadModelForm(data=request.POST, files=request.FILES)
if modelform.is_valid():
# 对于文件,自动保存至upload_to目录,img字段自动写入文件上传路径
modelform.save()
# print(modelform.instance.img) # city/haha.png
return redirect(settings.MEDIA_URL + str(modelform.instance.img))
return render(request, 'upload_list.html', {"modelform": modelform})
# 前端\django\myweb\blog\utils\form.py
# Form 文件上传
class UploadForm(BootStrapForm):
bootstrap_exclude_fields = ["img"]
name = forms.CharField(label="姓名")
age = forms.IntegerField(label="年龄")
img = forms.FileField(label="头像")
# ModelForm 文件上传
class UploadModelForm(BootStrapModelForm):
bootstrap_exclude_fields = ["img"]
class Meta:
model = City
fields = '__all__'
# 前端\django\myweb\blog\models.py
# Form文件上传
class Boss(models.Model):
name = models.CharField(verbose_name="姓名", max_length=32)
age = models.IntegerField(verbose_name="年龄")
img = models.CharField(verbose_name="头像",max_length=128) # 保存文件路径
# ModelForm文件上传
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/") # 本质上数据也是CharField,自动保存数据,upload_to 指的是media目录下指定目录