「Django框架」文件上传

一、前端实现
  1. 定义一个form表单,然后指定属性enctype="multipart/form-data",不然无法上传文件;
  2. 在上述表单中填入input组件,指定属性type="file"

以上代码示例如下:

<form action="" method="post" enctype="multipart/form-data">
	<input type="file" name="myfile" />
</form>

二、后端实现
1.基本方法

 Django会对接收的请求进行处理,于是在视图中可以直接从request对象中,通过FILES属性来获得上传的文件。在使用python的文件I/O操作,来实现上传文件的存储。

示例代码:

# 可以定义一个函数,完成文件存储操作
def save_file(file,file_name):
	with open(file_name,'wb') as fp:
		for chunk in file.chunks():
			fp.write(chunk)

def index(request):
	if request.method == 'GET':
		form = MyForm()
		return render(request,'index.html',{'form':form})
	else:
		myfile = request.FILES.get('myfile')
		save_file(myfile,"hello_world.txt")
		return HttpResponse('上传成功')

通过request.FILES获得的对象是一个字典,可以通过前端组件指定的name属性来获取特定的文件。

Django为文件对象附加了chunks方法,该方法以迭代器的形式返回固定大小的文件内容,避免一次性将数据读取到内存,主要用于处理大文件。

2.通过模型处理上传文件

 定义模型的时候,可以使用字段FileField存储文件,这个字段可以传递一个upload_to参数,用来指定上传的文件保存的位置。即上传的文件不是直接保存在数据库中的,而是保存到字段指定的目录下的。

# models.py
class Article(models.Model):
	title = models.CharField(max_length=100)
	content = models.TextField()
	thumbnail = models.FileField(upload_to='files')

# views.py
def index(request):
	if request.method == 'GET':
		return render(request,'index.html')
	else:
		title = request.POST.get('title')
		content = request.POST.get('content')
		thumbnail = request.FILES.get('thumbnail')
		article = Article(title=title,content=content,thumbnail=thumbnail)
		article = Article(title=title,content,thumbnail=thumbnai)
		article.save()
		return HttpResponse('success')

传入的upload_to参数是相对于项目目录下。如以上代码指定文件存储在项目下的files文件夹内。

在创建的模型对象上调用完save()后,就会把文件保存到指定目录下,并会将这个文件的路径存储到数据库中。

注意:若要使用表单对上传的数据进行验证,则必须将request.FILES传入表单构造函数中。如:

form = BlogForm(reuqest.POST,request.FILES)

否则表单无法读取上传的文件。

指定 MEDIA_ROOT 与 MEDIA_URL

 可以在settings.py中配置MEDIA_ROOT参数,这样就不需要在FileField中指定upload_to参数了,文件会自动上传到MEDIA_ROOT指定的目录下:

MEDIA_ROOT = os.path.join(BASE_DIR,'media')

 而MEDIA_URL用来指定前端访问时,模板中变量{{ MEDIA_URL }}访问的路径(相对于项目目录):

# settings.py
MEDIA_URL = '/media/'

# 项目文件夹的urls.py
from django.conf.urls.static import static
from django.conf import settings

urlpattern = [
	path('',views.index),
] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

MEDIA_RROTMEDIA_URL指向同一个文件夹。

若同时指定了MEDIA_ROOTupload_to参数,则文件会被上传到MEDIA_ROOT下的upload_to文件夹中。示例代码如下:

class Article(models.Model):
	title = models.CharField(max_length=100)
	content = models.TextField()
	thumbnail = models.FileField(upload_to="%Y/%m/%d")

MDEDIA_URL的使用

 配置MEDIA_URL使得我们可以在前端模板中通过模板变量{{ MEDIA_URL }}访问上传的文件,而要使用{{ MEDIA_URL }}还需:

  1. 在配置文件配置django.template.context_processors.media:
# settings.py中
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.media',		# 配置项
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
  1. DEBUG模式下,还需在项目的urls.py中配置路由:
# 项目文件夹的urls.py加入以下代码
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

三、限制上传的文件拓展名

 若想限制上传的文件的拓展名,那么就需要使用表单。可以使用普通的Form表单,也可以使用ModelForm,字节从模型中读取字段。
示例代码:

# models.py
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    thumbnial = models.FileField(upload_to='%Y/%m/%d/',validators=[validators.FileExtensionValidator(['txt','pdf'])])

# form.py
class ArticleForm(form.ModelForm):
	class Meta:
		model = Article
		fields = "__all__"

四、图片上传

 图片上传与普通文件的上传是一样的,只不过 Django 就会判断上传的文件是否是图片格式(除了判断后缀名,还会判断是否是可用的图片)。若不是,则验证会失败。在定义模型的时候定义存储图片的字段ImageField即可:

class Article(models.Model):
	title = models.CharField(max_length=100)
	content = models.TextField()
	thumbnail = models.ImageField(upload_to='%Y/%m/%d/')

 想要验证是否为合格的图片,直接使用ModelForm就可以了:

class MyForm(form.ModelForm):
	class Meta:
		model = Article
		fields = "__all__"

想要使用ImageField,需安装pillow库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值