08 Django - Django媒体文件静态文件文件上传
九、Django媒体文件&静态文件&文件上传
1.静态文件和媒体文件
- 媒体文件: 用户上传的文件, 叫做
media
- 静态文件: 存放在服务器的 css, js, image等,叫做
static
在Django中使用静态文件
{% static 'img/example.jpg' %}
=> static模板关键字就是在settings.py中指定的静态文件夹中(应用下的static
文件夹和STATICFILES_DIR
寻找到符合条件的静态文件- 然后将
相对路径写入
html标签中 注意
: 应用下的static文件夹里的文件(包括STATICFILES_DIR下的文件) 似乎在网站生成时都统一放在了http://127.0.0.1:8000/static/
下
首先确保django.contrib.staticfiles在INSTELLED_APPS中
2) 在 setting.py中定义 SRARIC_URL
STATIC_URL = '/static/'
3) 在你的app的static目录中存放静态文件,比如
APP/ static/ example.jpg
4) 如果有别的静态文件,不在app的static目录下,可以通过 STATICFILES_DIRS来指定额外的静态搜索目录
STATICFILES_DIR = [
os.path.join(BASE_DIR, 'static'),
...
]
5) 在模板中使用load标签去加载文件
{% load static %}
<img src="/static/index.css" />
<img src="{% static 'img/example.jpg' %}" />
在django中使用媒体文件
在settings中配置 MEDIA_ROOT
, 就是指定文件上传的路径选项
MEDIA_ROOT = os.path.join(BASE_DIR,"media")
2. 文件上传
单文件上传
文件上传要求form表单存在enctype="multipart/form-data"属性,并且提交方法是post。
<form enctype="multipart/form-data" action="/uploadFile/" method="post">
<input type="file" name="myfile" />
<br/>
<input type="submit" value="upload"/>
</form>
最简单的文件上传:
def file_upload(request):
if request.method =='POST':
# 获取上传的文件,如果没有文件,则默认为None
myFile = request.FILES.get('myfile', None)
if not myFile:
return HttpResponse("no files for upload")
file_path = os.path.join(settings.MEDIA_ROOT, '1.jpg')
with open(file_path, 'ab') as fp:
for part in myFile.chunks():
fp.write(part)
return HttpResponse("上传成功!")
else:
return render(request, 'index.html')
单文件上传案例
views.py
import os
import uuid
from django.conf import settings
from django.shortcuts import redirect, render
from django.urls import reverse
from App.models import *
# Create your views here.
def index(request):
return render(request, 'index.html')
def index2(request):
return render(request, 'index2.html')
# 单文件上传
def upload1(request):
if request.method == 'GET':
return render(request, 'upload1.html')
elif request.method == 'POST':
# 单文件上传
uname = request.POST.get('uname')
icon = request.FILES.get('icon') # 单个文件
print(uname, icon, type(icon))
# 1.将上传的图片存储到后台对应的媒体文件中
# file_name = icon.name # 尽量不要使用图片的原始名称, 避免重复
# file_name = get_uuid() + icon.name[icon.name.rfind('.'):] # 获取后缀名
file_name = get_uuid() + os.path.splitext(icon.name)[-1] # 获取后缀名
file_path = os.path.join(settings.MEDIA_ROOT , file_name)
print(file_path)
with open(file_path, 'wb') as f:
for chunk in icon.chunks(): # 分块写入
f.write(chunk)
f.flush() # 立即写入
# 2.将该媒体文件的路径,存入到数据库中
user = UserModel()
user.name = uname
user.icon = 'uploads/' + file_name # 注意: 存储的是相对路径, 而不是绝对路径,相对于static的路径
user.save()
return render(request, 'upload1.html')
# 获取uuid, 用于生成唯一的文件名
def get_uuid():
return str(uuid.uuid4())
def showicon(request, uid):
if uid == None: # 如果没有传uid, 则默认为1
uid = 1
# 显示用户的头像
user = UserModel.objects.filter(id=uid).first()
print(user, user.name, user.icon)
return render(request, 'showicon.html', {'user': user})
# 多文件上传
def upload2(request):
if request.method == 'GET':
return render(request, 'upload2.html')
elif request.method == 'POST':
# 接收前端的参数
uname = request.POST.get('uname')
uid = UserModel.objects.filter(name=uname).first().id
imgs = request.FILES.getlist('imgs') # 多个文件
print(uname, imgs, type(imgs))
# [<InMemoryUploadedFile: chapter11_主界面.png (image/png)>, <InMemoryUploadedFile: chapter12_对话框.png (image/png)>] <class 'list'>
# 遍历文件列表, 依次上传
for img in imgs:
# 1.将上传的图片存储到后台对应的媒体文件中
file_name = get_uuid() + os.path.splitext(img.name)[-1] # 获取后缀名
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
with open(file_path, 'wb') as f:
for chunk in img.chunks(): # 分块写入
f.write(chunk)
f.flush() # 立即写入
# 2.将该媒体文件的路径,存入到数据库中
photo = PhotoModel()
photo.img = 'uploads/' + file_name
photo.user = UserModel.objects.filter(name=uname).first()
photo.save()
return redirect(reverse('showicon',kwargs={'uid': uid}))
settings.py
STATIC_URL = 'static/'
STATICFILES_DIRS = [
BASE_DIR / 'static'
]
MEDIA_ROOT = BASE_DIR /'static/uploads'
models.py
from django.db import models
# Create your models here.
class UserModel(models.Model):
name = models.CharField(max_length=32, unique=True)
# 头像(存储头像的路径)
icon = models.CharField(max_length=128)
upload1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件上传</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>用户名: <input type="text" name='uname'></p>
<p>头像: <input type="file" name="icon"></p>
<button>上传</button>
</form>
</body>
</html>
showicon.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>显示图标</title>
</head>
<body>
<h1>显示图标</h1>
<hr>
{% load static %}
<p>{{user.name}}</p>
<img src="{% static user.icon %}" alt="">
</body>
</html>
多文件上传
多文件上传和单文件上传类似
1.需要在模板文件的form表单input中添加multiple
2.后台获取时使用request.FILES.getlist('myfile', None)
def file_upload2(request):
if request.method == 'POST':
# 获取上传的文件,如果没有文件,则默认为None
myFiles = request.FILES.getlist('myfile', None)
for myFile in myFiles:
if not myFile:
return HttpResponse("no files for upload")
file_path = os.path.join(settings.MEDIA_ROOT, myFile.name)
with open(file_path, 'ab') as fp:
for part in myFile.chunks():
fp.write(part)
return HttpResponse("上传成功!")
else:
return render(request, 'index.html')
多文件上传案例
views.py
import os
import uuid
from django.conf import settings
from django.shortcuts import redirect, render
from django.urls import reverse
from App.models import *
# Create your views here.
def index(request):
return render(request, 'index.html')
def index2(request):
return render(request, 'index2.html')
# 单文件上传
def upload1(request):
if request.method == 'GET':
return render(request, 'upload1.html')
elif request.method == 'POST':
# 单文件上传
uname = request.POST.get('uname')
icon = request.FILES.get('icon') # 单个文件
print(uname, icon, type(icon))
# 1.将上传的图片存储到后台对应的媒体文件中
# file_name = icon.name # 尽量不要使用图片的原始名称, 避免重复
# file_name = get_uuid() + icon.name[icon.name.rfind('.'):] # 获取后缀名
file_name = get_uuid() + os.path.splitext(icon.name)[-1] # 获取后缀名
file_path = os.path.join(settings.MEDIA_ROOT , file_name)
print(file_path)
with open(file_path, 'wb') as f:
for chunk in icon.chunks(): # 分块写入
f.write(chunk)
f.flush() # 立即写入
# 2.将该媒体文件的路径,存入到数据库中
user = UserModel()
user.name = uname
user.icon = 'uploads/' + file_name # 注意: 存储的是相对路径, 而不是绝对路径,相对于static的路径
user.save()
return render(request, 'upload1.html')
# 获取uuid, 用于生成唯一的文件名
def get_uuid():
return str(uuid.uuid4())
def showicon(request, uid):
if uid == None: # 如果没有传uid, 则默认为1
uid = 1
# 显示用户的头像
user = UserModel.objects.filter(id=uid).first()
print(user, user.name, user.icon)
return render(request, 'showicon.html', {'user': user})
# 多文件上传
def upload2(request):
if request.method == 'GET':
return render(request, 'upload2.html')
elif request.method == 'POST':
# 接收前端的参数
uname = request.POST.get('uname')
uid = UserModel.objects.filter(name=uname).first().id
imgs = request.FILES.getlist('imgs') # 多个文件
print(uname, imgs, type(imgs))
# [<InMemoryUploadedFile: chapter11_主界面.png (image/png)>, <InMemoryUploadedFile: chapter12_对话框.png (image/png)>] <class 'list'>
# 遍历文件列表, 依次上传
for img in imgs:
# 1.将上传的图片存储到后台对应的媒体文件中
file_name = get_uuid() + os.path.splitext(img.name)[-1] # 获取后缀名
file_path = os.path.join(settings.MEDIA_ROOT, file_name)
with open(file_path, 'wb') as f:
for chunk in img.chunks(): # 分块写入
f.write(chunk)
f.flush() # 立即写入
# 2.将该媒体文件的路径,存入到数据库中
photo = PhotoModel()
photo.img = 'uploads/' + file_name
photo.user = UserModel.objects.filter(name=uname).first()
photo.save()
return redirect(reverse('showicon',kwargs={'uid': uid}))
upload2.html
文件多选 -> multiple
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>多文件上传</title>
</head>
<body>
{% comment %} multipart/form-data支持文件上传 {% endcomment %}
{% comment %} multiple: 支持文件多选 {% endcomment %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>用户名: <input type="text" name='uname'></p>
<p>选择上传的图片: <input type="file" name="imgs" multiple></p>
<button>上传</button>
</form>
</body>
</html>
showicon.html
添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>显示图标</title>
</head>
<body>
<h1>显示图标</h1>
<hr>
{% load static %}
<p>{{user.name}}</p>
<p>头像<img src="{% static user.icon %}" alt=""></p>
<hr>
<h3>{{user.name}}的相册</h3>
{% for photo in user.photomodel_set.all %}
<img src="{% static photo.img %}" alt="" width=100>
{% endfor %}
</body>
</html>