Django文件上传和图片上传

文件上传:

文件上传是网站开发中非常常见的功能。接下来就将详细讲述如何在Django中实现文件的上传功能。

前端HTML代码实现:

  1. 在前端中,我们需要填入一个form标签,然后在这个form标签中指定enctype=“multipart/form-data”,不然就不能上传文件。
  2. 在form标签中添加一个input标签,然后指定input标签的name(即上传文件我们想要它显示的名字),以及type=“file”。

新建一个file.html的文件,body中写入:

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

后端的代码实现:

后端的主要工作是接收文件。然后存储文件。接收文件的方式跟接收POST的方式是一样的,只不过是通过FILES来实现。示例代码如下:

在views中添加视图函数:

from django.shortcuts import render
from django.views.generic import View
from django.http import HttpResponse

# Create your views here.
class IndexView(View):
    def get(self,request):
        return render(request,'file.html')
    def post(self,request):
        myfile = request.FILES.get('myfile')
        with open('files.txt','wb') as fp:
            for chunk in myfile.chunks():
                fp.write(chunk)
        return HttpResponse('success')

然后在urls中添加映射,我们就可以运行项目了,
然后我们就可以选取本地的文件进行上传了。

使用模型来处理上传的文件:

在定义模型的时候,我们可以给存储文件的字段指定为FileField,这个Field可以传递一个upload_to参数,用来指定上传上来的文件保存到哪里。比如我们让他保存到项目的files文件夹下,那么示例代码如下:

在models中新建一个模型:

from django.db import models

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    file = models.FileField(upload_to='files')

因为我们指定了上传到files文件夹中,所以我们需要手动在项目的根目录下新建一个文件夹files,然后在视图中添加视图:

from .models import Article

class ArticleView(View):
    def get(self,request):
        return render(request,'file.html')
    def post(self,request):
        title = request.POST.get('title')
        content = request.POST.get('content')
        file = request.FILES.get('myfile')
        Article.objects.create(title=title,content=content,file=file)
        return HttpResponse('success')

这里我们继续渲染的时上面那个示例的模板,所以我们需要在上面的模板中添加两个input标签,在file.html中的body中写入:

<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title"><br>
    <input type="text" name="content"><br>
    <input type="file" name="myfile"><br>
    <input type="submit" value="提交"><br>
form>

然后我们在urls中添加映射,就能够正常的进行访问了。

注意: 在数据库中file字段保存的是文件的路径,而不是文件的信息。

指定MEDIA_ROOT和MEDIA_URL:

1. MEDIA_ROOT

上面我们是使用了upload_to来指定上传的文件的目录。我们也可以指定MEDIA_ROOT,就不需要在FielField中指定upload_to,他会自动的将文件上传到MEDIA_ROOT的目录下。

在settingsz.py中最下面添加代码:

# 指定上传的文件存放位置
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
# 获取上传的文件的url
MEDIA_URL = '/media/'

然后我们将上面的files文件夹修改一个文件名为media。并且可以将file字段中的upload_to参数也去掉。

这样,我们也能将文件上传至我们指定的media目录下。

但是,这样就产生了一个问题,随着网站越来越大,那么文件上传的次数肯定也多了,全部都放在media目录下不方便我们管理。所以者恶搞时候我们可以对文件存储的位置进一步划分。
我们在file字段中继续传入一个参数upload_to

    file = models.FileField(upload_to='files')

这样,因为我们在settings中设置了MEDIA_ROOT参数,所以Django会先去查找MEDIA_ROOT参数中的值,然后再寻找upload_to中的值,所以最后上传的文件的路径为media/files/< filename >

当然我们也可以按照时间来进行储存,只需要改变upload_to的值就行了。

    file = models.FileField(upload_to='%Y/%m/%d/')

然后就会在media下生成一个年/月/日的文件夹。并且将我们上传的文件放入里面。

2. MEDIA_URL

如果我们想要访问上传的文件,那么我们直接输入网址

127.0.0.1:8000/media/

是访问不到的,那么我们应该怎样来进行访问呢。
这个时候我们就需要使用到MEDIA_URL了。

在主urls中添加代码

from django.urls import path,include

from django.conf.urls.static import static
# 导入settings文件,就能得到settings中的所有东西
from django.conf import settings

urlpatterns = [
    path('front/', include('front.urls')),
    path('file/',include('file.urls')),
] + static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)

这样,我们就可以像上面那样输入网址对文件进行访问了。

因为static函数返回的是一个列表,所以我们用+对他们进行连接,就会把static返回的列表中的值放入urlpatterns这个列表中。如果文件时图片也是一样可以访问的。

限制上传的文件拓展名:

为什么我们需要限制上传文件的扩展名呢,因为如果别人上传一些后缀名为.py、.php等文件,那么这些文件是可以被运行的,那么就对我们的网站存在着极大的安全隐患。所以我们需要限制文件上传的后缀名。

如果想要限制上传的文件的拓展名,那么我们就需要用到表单来进行限制。我们可以使用普通的Form表单,也可以使用ModelForm,直接从模型中读取字段。

首先修改models中的代码,给file字段添加一个validators

from django.db import models
from django.core import validators

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # 只允许上传txt文件
    file = models.FileField(upload_to='%Y/%m/%d/',validators=[validators.FileExtensionValidator(['txt'],message='file必须为txt文件')])

然后我们使用modelForm对数据进行验证,新建一个forms.py文件,写入代码:


from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'

然后修改Views中的ArticleView视图,将里面的post函数注释掉,然后重新写入一个post函数

    def post(self,request):
        # request.POST,对普通字段进行验证
        # request.FILES 对文件字段进行验证
        form = ArticleForm(request.POST,request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponse('success')
        else:
            print(form.errors.get_json_data())
            return HttpResponse('fail')

因为我们使用的是modelForm,所以前端传入数据的name属性一定要和model中的字段名一样。所以我们修改file.html中的代码

<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title"><br>
    <input type="text" name="content"><br>
{#    
#}
<input type="file" name="file"><br> <input type="submit" value="提交"><br> </form>

这样,就完成了我们的代码,就可以输入网址进行测试效果了。

上传图片:

上传图片跟上传普通文件是一样的。只不过是上传图片的时候Django会判断上传的文件是否是图片的格式(除了判断后缀名,还会判断是否是可用的图片)。如果不是,那么就会验证失败。

这里我们就修改models中的字段就行了,就不去添加新的字段了。

models中修改代码:

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # 只允许上传txt文件
    # file = models.FileField(upload_to='%Y/%m/%d/',validators=[validators.FileExtensionValidator(['txt'],message='file必须为txt文件')])
    # 上传图片
    file = models.ImageField(upload_to='%Y/%m/%d/')

forms中修改代码:

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'
        error_messages = {
            'file':{
                'invalid_image':'请上传正确格式的图片~~',
            },
        }

然后就能对图片进行上传了,ImageField字段在底层会帮我们进行验证是否为可用的图片,如果不是,就会返回错误。

注意: 使用ImageField,必须要先安装Pillow库:pip install pillow,如果安装了pillow库,仍然有错误的话,应该就是pillow库版本过低,可以安装指定的最新版本:
目前我的最新版本为5.3.0。可以输入以下命令安装

pip install pillow==5.3.0

想深入学习django的可以看一下这个视频:超详细讲解Django打造大型企业官网

你可能感兴趣的:(django)