django实现文件上传

在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 %}

效果:

数据库存储的:

相关推荐
cyt涛1 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油2 小时前
01_SQLite
数据库·sqlite
向上的车轮2 小时前
Django学习笔记五:templates使用详解
笔记·学习·django
liuxin334455662 小时前
教育技术革新:SpringBoot在线教育系统开发
数据库·spring boot·后端
看山还是山,看水还是。3 小时前
MySQL 管理
数据库·笔记·mysql·adb
fishmemory7sec3 小时前
Koa2项目实战2(路由管理、项目结构优化)
数据库·mongodb·koa
momo小菜pa3 小时前
【MySQL 09】表的内外连接
数据库·mysql
Jasonakeke3 小时前
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
数据库·mysql
程序猿小D3 小时前
第二百六十九节 JPA教程 - JPA查询OrderBy两个属性示例
java·开发语言·数据库·windows·jpa
小宇成长录3 小时前
Mysql:数据库和表增删查改基本语句
数据库·mysql·数据库备份