django 利用Form上传文件到 media 文件夹

背景:利用 Form 收集用户提交的信息,包括字符串和文件对象,文件保存在项目的 media 文件夹,因为 static 文件一般是用来存静态文件 css 或者项目所需要的图片,用户上传的文件应该保存在其他文件夹;

1、 启用 media,在项目根目录创建 media 文件夹(与manage.py文件同级)

urls.py 需要新增如下

...
from django.urls import 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'),
...

]

settings.py 需要新增如下

MEDIA_ROOT = os.path.join(BASE_DIR,"media")
MEDIA_URL = "/media/"

2、设置好之后在 media 文件夹下放一个图片就能够直接访问了

3、 案例:

用户上传自己的姓名、年龄、头像

 上传成功之后:查看数据库

 4、案例实现

4.1、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)

 4.2、创建 url 链接

from .views import upload_form
urlpatterns = [
    path('upload/form',upload_form),# form 上传
]

4.3、创建视图函数 views.py

def upload_form(request):
    title = "Form上传"
    if request.method == 'GET':
        form = UpForm()
        return render(request,'upload_form.html',{"form":form,"title":title})
    if request.method == 'POST':
        form = UpForm(data=request.POST,files=request.FILES)
        if form.is_valid():
            print(form.cleaned_data)
            # {'name': '测试', 'age': 23, 'img': <InMemoryUploadedFile: 电信科技.png (image/png)>}
            # 1、读取图片内容,写入到文件夹中并获取文件的路径
            image_object = form.cleaned_data.get("img")
            # file_path = "appback/static/img/{}".format(image_object.name)  # 这种写法不同操作系统会出问题
            # file_path = os.path.join("appback","static","img",image_object.name) # 将文件写入appback/tatic/img
            from django.conf import settings
            # db_file_path = os.path.join(settings.MEDIA_ROOT,image_object.name) # 将文件写入 media 文件夹 settings.MEDIA_ROOT # 绝对路径
            db_file_path = os.path.join("media", image_object.name)
            f = open(db_file_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=db_file_path
            )
            return HttpResponse('...')
        return render(request,'upload_form.html',{"form":form,"title":title})

tips1:文件路径建议使用 os.path.join 拼接而不要使用下面这种方式,因为linux 与 windows 不同操作系统可能会出现问题。

file_path = "appback/static/img/{}".format(image_object.name)

tips2:存入数据库的是文件的路径,可以是绝对路径也可以是相对路劲。

绝对路径:

db_file_path = os.path.join(settings.MEDIA_ROOT,image_object.name)

相对路径:

db_file_path = os.path.join("media", image_object.name)

tips3: 文件是分块上传的到内存的,因此保存的时候利用循环读取保存到本地

例如上传一个excel 文件,上传成功以后打印它的文件对象类型

 <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

file_object = request.FILES.get('excel')
print(type(file_object)) # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>

查看这个对象的方法,按住ctrl 点击 InMemoryUploadedFile

from django.core.files.uploadedfile import  InMemoryUploadedFile

可以看到这个对象中的方法,这里我们需要把这个文件对象读出来,保存到本地,因此使用对象的 chunks 方法。

f = open(db_file_path,mode="wb")
for chunk in image_object.chunks():
    f.write(chunk)
f.close()

tips4:如果是 excel 可以直接使用第三方 openpyxl 库直接读取文件对象,因为它load_workbook支持传入一个文件对象。

from openpyxl import load_workbook
wb = load_workbook(file_object)

4.4 模板文件html

<!--该html 继承模板 layout.html-->
{% extends 'layout.html' %}
{% block content %}
      <div>
        <h3>{{title}}</h3>
        <form method="post" enctype="multipart/form-data" novalidate>
          {% csrf_token %}
          {% for field in form %}
            {{ field.label }}:{{field}}
            <span style="color:red;">{{field.errors.0}}</span>
          {% endfor %}
          <input type="submit" value="提交">
        </form>
      </div>
{% endblock %}

以上就是利用 Form 收集用户提交的数据包括上传的文件保存到本地,写入数据库中的全部内容了。下期更新更简单的 ModelForm 上传。

ModelForm 上传:

1、创建一张表

class City(models.Model):
    name = models.CharField(verbose_name="名称", max_length=32)
    count = models.IntegerField(verbose_name="人口")
    img = models.FileField(verbose_name="Logo", upload_to="city/")

 upload_to="city/"  用户上传的文件将会保存到 media/city 文件夹下

2、url.py

path('upload/modelform',upload_modelform)

3、视图函数

class UpmodelForm(forms.ModelForm):
    class Meta:
        model = City
        fields = "__all__"
def upload_modelform(request):
    title = "modelFoem上传"
    if request.method == 'GET':
        form = UpmodelForm()
        return render(request,'upload_form.html',{"form":form,"title":title})
    if request.method == 'POST':
        form = UpmodelForm(data=request.POST,files=request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponse("成功")
        return render(request,'upload_form.html',{"form":form,"title":title})

查看数据库发现提交成功

可以发现 modelForm 比Form 更加简单。

图片展示在页面上

{% for obj in forms %}
<img src="/media/{{obj.img}}" style="width:100px;height:100px;">
{% endfor %}

 

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值