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/
python 复制代码
 首先确保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, 就是指定文件上传的路径选项

python 复制代码
MEDIA_ROOT = os.path.join(BASE_DIR,"media")

2. 文件上传

单文件上传
python 复制代码
文件上传要求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

python 复制代码
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

python 复制代码
STATIC_URL = 'static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static'
]
MEDIA_ROOT = BASE_DIR /'static/uploads'

models.py

python 复制代码
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

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

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>
多文件上传
python 复制代码
多文件上传和单文件上传类似
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

python 复制代码
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

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>
    {% 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添加

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>
相关推荐
测试杂货铺2 分钟前
UI自动化测试实战实例
自动化测试·软件测试·python·selenium·测试工具·测试用例·pytest
KELLENSHAW23 分钟前
MySQL45讲 第三十七讲 什么时候会使用内部临时表?——阅读总结
数据库·mysql
余~~1853816280024 分钟前
NFC 碰一碰发视频源码搭建技术详解,支持OEM
开发语言·人工智能·python·音视频
苏三有春35 分钟前
PyQt实战——使用python提取JSON数据(十)
python·json·pyqt
allnlei1 小时前
自定义 Celery的logging模块
python·celery
帅逼码农1 小时前
python爬虫代码
开发语言·爬虫·python·安全架构
跟德姆(dom)一起学AI1 小时前
0基础跟德姆(dom)一起学AI 自然语言处理05-文本特征处理
人工智能·python·深度学习·自然语言处理
爪哇抓挖_Java1 小时前
M系列芯片切换镜像源并安装 openJDK17
前端·chrome·python
小刘鸭!2 小时前
Hbase的特点、特性
大数据·数据库·hbase
AI人H哥会Java2 小时前
【Spring】控制反转(IoC)与依赖注入(DI)—IoC容器在系统中的位置
java·开发语言·spring boot·后端·spring