文件上传
实现图片的上传并保存到服务器中
编辑myproject/employee_management/templates/layout.html
<li><a href="/upload/list/">上传图片</a></li>
编辑myproject/myproject/urls.py
# 文件上传
path('upload/list/', upload.upload_list),
新建myproject/employee_management/views/upload.py
import re
from django.shortcuts import render,HttpResponse
def upload_list(request):
if request.method == "GET":
return render(request, "upload_list.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("上传成功")
新建myproject/employee_management/templates/upload_list.html
注意:
下面代码中的form
标签中必须加上enctype="multipart/form-data"
才能实现图片的上传
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<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表格上传
实现:表格上传至服务器并将数据读取保存至数据库中
我们在部门管理
代码的基础上进行操作
编辑myproject/employee_management/templates/depart_list.html
<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>
安装openpyxl
pip3 install openpyxl
编辑myproject/employee_management/views/depart.py
from django.shortcuts import render, redirect, HttpResponse
from openpyxl import load_workbook
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("上传成功")
编辑myproject/myproject/urls.py
path('depart/multi/', depart.depart_multi),
浏览器访问测试
手动创建一个表格,填入如下内容
将表格进行上传
上传成功
返回部门列表并刷新页面
这里会存在一个问题,如果上传的字段就为空,页面就会报错
处理起来也简单,针对为空的情况做一下简单的判断即可
Form图片上传
编辑myproject/employee_management/views/upload.py
from django.shortcuts import render,HttpResponse
from employee_management.utils.modelform import BootStrapForm
from django import forms
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})
编辑myproject/myproject/urls.py
path('upload/form/', upload.upload_form),
新建myproject/employee_management/templates/upload_form.html
注意: 需要在
<form>
标签中添加enctype="multipart/form-data"
属性
{% 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>
浏览器访问,会发现有一个问题,详情如下:
解决方式如下:
编辑myproject/employee_management/utils/modelform.py
class BootStrapForm(forms.Form):
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"
else:
field.widget.attrs = {
"class": "form-control",
}
编辑myproject/employee_management/views/upload.py
bootstrap_exclude_fields = ['img']
浏览器刷新
在 Django 的开发中有两个特殊的文件夹:
- static: 存放静态文件
- media:存放用户上传的数据,但是使用 media 需要做一些配置
media的配置:
编辑myproject/myproject/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'),
]
编辑myproject/myproject/settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = '/media/'
新建目录myproject/media
接下来实现图片的上传(保存至本地与数据库)
创建一个新的数据库
编辑myproject/employee_management/models.py
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)
在服务器中项目根目录下执行命令
python3 manage.py makemigrations
python3 manage.py migrate
编辑myproject/employee_management/views/upload.py
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)
# django 默认从 app 下开始找文件,也就是目前的 employee_management 下,所以存入数据库时不必加上 employee_management
# 例如 http://127.0.0.1/static/img/image.png
# file_path_db = os.path.join("static", "img", image_object.name)
# file_path = os.path.join("employee_management", file_path_db)
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})
浏览器测试
查看本地media
目录
查看数据库
ModelForm图片上传(推荐)
使用 ModelForm 方式进行图片的存储将更加便捷,看代码即可有体会
编辑myproject/employee_management/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/')
在服务器中项目根目录下执行命令
python3 manage.py makemigrations
python3 manage.py migrate
然后优化一下BootStrap工具类(之前忘了弄了,这里补充一下)
编辑myproject/employee_management/utils/modelform.py
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"
else:
field.widget.attrs = {
"class": "form-control",
}
class BootStrapModelForm(BootStrap, forms.ModelForm):
pass
class BootStrapForm(BootStrap, forms.Form):
pass
编辑myproject/myproject/urls.py
path('upload/model/form/', upload.upload_model_form),
编辑myproject/employee_management/views/upload.py
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})
编辑myproject/employee_management/templates/layout.html
<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>
浏览器测试
返回则上传成功
查看数据库中是否保存
查看本地文件是否保存
城市列表
使用一个例子简单应用一下上面的内容
编辑myproject/myproject/urls.py
# 城市管理
path('city/list/', city.city_list),
path('city/add/', city.city_add),
新建myproject/employee_management/views/city.py
from employee_management.utils.modelform import BootStrapModelForm
from django.shortcuts import render, redirect
from employee_management.models import City
from employee_management.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})
新建myproject/employee_management/templates/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 %}
编辑myproject/employee_management/templates/layout.html
<li><a href="/city/list/">城市管理</a></li>
浏览器访问测试
至此,Django的学习之旅到此结束,
但是对于我们热爱学习的童鞋来说,这只是旅途的开始,前方还有未知的道路等待我们去探索,
学无止境,用于求知,付诸行动,让我们迈向更好的明天,加油吧,少年们!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100692.html