在django中实现文件上传有三种方法可以实现:
- 自己手动写
- 使用Form组件
- 使用ModelForm组件
其中使用ModelForm组件实现是最简单的。
1、自己手写
先写一个上传的页面 upload_file.html
enctype="multipart/form-data 一定要加这个,不然只会上传文件名,不会上传文件内容。
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 %}
在写一个视图函数:
在这个视图函数中如果是get 请求就展示上传的页面,如果是post 请求,就将获取到的文件对象在项目跟目录创建一个相同的文件名保存起来。
python
from django.shortcuts import render, HttpResponse
def upload_list(request):
if request.method == 'GET':
return render(request,'upload_file.html')
print(request.POST) # 请求体中的数据
print(request.FILES) # 请求发过来的文件 {}
file_object = request.FILES.get("avatar")
f = open(file_object.name,mode='wb')
for chunk in file_object.chunks():
f.write(chunk)
f.close()
return HttpResponse('上传成功')
简单的页面效果:
2、使用Form组件
提交页面时: 用户输入数据 + 文件(输入不能为空,报错)
- Form生成HTML标签 :type=file
- 表单的验证
- form.cleaned_data 获取数据 + 文件对象
将上传的图片保存到static目录,并且在数据库保存文件存储的路径
models.py 中创建一个数据库
python
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)
视图函数
python
from django.shortcuts import render, HttpResponse
from django import forms
import os
from app01 import models
class UpForm(forms.Form):
name = forms.CharField(label='姓名')
age = forms.IntegerField(label='年龄')
img = forms.FileField(label='头像')
def upload_form(request):
if request.method == 'GET':
form = UpForm()
return render(request,'upload_form.html',{'form':form})
form = UpForm(data=request.POST,files=request.FILES)
if form.is_valid():
# 1、读取图片内容,写入文件夹中并获取文件的路径
image_object = form.cleaned_data.get('img')
# 创建文件路径
db_file_path = os.path.join('static','img',image_object.name)
file_path = os.path.join('app01',db_file_path)
f = open(file_path,mode='wb')
for chunk in image_object.chunks():
f.write(chunk)
f.close()
# 2、 将图片文件路径写入到数据库
models.Boss.objects.create(
name=form.cleaned_data['name'],
age = form.cleaned_data['age'],
img = db_file_path,
)
return HttpResponse('上传成功')
return render(request,'upload_form.html',{'form':form})
upload_form.html 文件内容:
html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">图片上传</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 %}
页面效果:
3、使用ModelForm组件
使用ModelForm的前提条件要设置好media 目录
启用media 目录
在django的开发中有两个特殊的文件夹:
- static , 存放静态文件的路径,包括: css、js 、项目图片。
- media , 用户上传的数据目录。
1、在urls.py中的配置
python
from django.urls import path,re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
re_path(r'^media/(?P<path>.*)$', serve, {'document_root':settings.MEDIA_ROOT},name='media'),
]
2、在settings.py中配置:
python
import os
MEDIA_ROOT = os.path.join(BASE_DIR,"media")
MEDIA_URL = "/media/"
models.py 重新创建一个表来存储文件路径
python
class City(models.Model):
"""城市"""
name = models.CharField(verbose_name="名称",max_length=32)
count = models.IntegerField(verbose_name="人口")
# 本质上数据库也是charField ,自动保存数据,upload_to 表示会保存到media目录下的city
img = models.FileField(verbose_name='Logo',max_length=128,upload_to='city/')
视图函数:
通过 form.save() django 自动将文件存储到media目录下的city目录,并且把文件路径保存到数据库
python
from django.shortcuts import render, HttpResponse
from app01 import models
from app01.utils.bootstrap import BootStrapModelForm
class UploadModelForm(BootStrapModelForm):
bootstrap_exclude_name = ['img']
class Meta:
model = models.City
fields = "__all__"
def upload_modelform(request):
if request.method == 'GET':
form = UploadModelForm()
return render(request,'upload_form.html',{'form':form})
form = UploadModelForm(data=request.POST,files=request.FILES)
if form.is_valid():
form.save()
return HttpResponse('上传成功')
return render(request, 'upload_form.html', {'form': form})
upload_form.html
html
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">图片上传</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 %}
效果:
数据库存储的: