南飓风 发表于 2024-12-26 19:11:29

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 # 获取后缀名
      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 # 获取后缀名
      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>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 08 Django - Django媒体文件&静态文件&文件上传