django之文件上传下载等相关

一、文件上传

利用Django实现一个简单的文件上传功能。

实现步骤: 1)创建项目Django_upload:django-admin startproject Django_upload;创建app:cd Django_upload;python manage.py startapp blog。 2)设计模型(M) 这里的模型只包括了两个属性:用户名(即谁上传了该文件);文件名。具体形式如下所示: #coding=utf-8 from __future__ import unicode_literals from django.db import models class NormalUser(models.Model): username=models.CharField('用户名',max_length=30) #用户名 headImg=models.FileField('文件',upload_to='./upload')#文件名 def __str__(self): return self.username class Meta: ordering=['username']#排序风格username 同步数据库:Python manage.py makemigrations python manage.py migrate 3)设计视图(V) view.py: #coding=utf-8 from django.shortcuts import render,render_to_response from django import forms from django.http import HttpResponse from blog.models import * # Create your views here. class NormalUserForm(forms.Form): #form的定义和model类的定义很像 username=forms.CharField() headImg=forms.FileField() #在View中使用已定义的Form方法 def registerNormalUser(request): #刚显示时调用GET方法 if request.method=="POST": uf = NormalUserForm(request.POST,request.FILES)#刚显示时,实例化表单(是否有数据) if uf.is_valid():#验证数据是否合法,当合法时可以使用cleaned_data属性。 #用来得到经过'clean'格式化的数据,会所提交过来的数据转化成合适的Python的类型。 username = uf.cleaned_data['username'] headImg = uf.cleaned_data['headImg'] #write in database normalUser=NormalUser()#实例化NormalUser对象 normalUser.username = username normalUser.headImg = headImg normalUser.save()#保存到数据库表中 return HttpResponse('Upload Succeed!')#重定向显示内容(跳转后内容) else: uf=NormalUserForm()#刚显示时,实例化空表单 return render(request,'register.html',{'uf':uf})#只有刚显示时才起作用 配置urls.py: from django.conf.urls import url from django.contrib import admin from blog.views import * urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register/$',registerNormalUser), ] 4)设计模板与表单(T)templates/register.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Register</title> </head> <body> <h2 align="center">Register</h2> <form method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ uf.as_p }} <input type="submit" value="Submit"> </form> </body> </html> 在这里,表单方法为POST,enctype=”multipart/form-data”:表单数据被编码为一条消息。(一般用于传输二进制文件(图片、视频)) {% csrf_token %}: 跨域请求,我们需要在表单标签的内部加上这个模板标签,而且要在views.py中配合render不是render_to_response来实现。 {{ uf.as_p }}:这样一次性可以把表单里的所有字段给显示处理 显示结果: 上传 提交表单后: 提交表单 补充form显示单个元素: {{ field.label_tag }}: {{ field }} 比如我的form有个qq字段。那么就是这样写: {{ form.qq.label_tag }}#表示在form 里面定义这个字段的名称 {{ form.qq }}#根据这个字段在form定义的类型来决定。假设是char类型。那就是文本框 {{ form.qq.errors.as_text }}表示如果表单字段验证失败的话,这个代表错误信息 {{ form.qq.help_text }}如果你在form里定义了这个字段的帮助信息的话,就会在这里显示了 Django处理文件上传File Uploads HttpRequest.FILES 表单上传的文件对象存储在类字典对象request.FILES中,表单格式需为multipart/form-data <form enctype="multipart/form-data" method="post" action="/foo/"> <input type="file" name="image" /> request.FILES中的键来自于表单中的<input type="file" name="" />的name值: img=request.FILES['image'] request.FILES中的值均为UploadedFile类文件对象。 UploadedFile UploadedFile是类文件对象,具有以下方法和属性: UploadedFile.read() 读取整个上传文件的数据,文件较大时慎用。 UploadedFile.multiple_chunks(chunk_size=None) 判断文件是否足够大,一般为2.5M UploadedFile.chunks(chunk_size=None) 返回一个生成器对象,当multiple_chunks()为True时应该使用这个方法来代替read(). UploadedFile.name 上传文件的name。 UploadedFile.size 上传文件的大小。 UploadedFile.content_type 上传文件时的content_type报头,例如(e.g. text/plain or application/pdf). UpladedFile.charset 编码 存储文件 想将上传的文件存储在本地时: f=request.FILES['image'] with open('some/file/name.txt', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) 使用Form处理上传文件 也可以使用django自带的form来处理上传文件。 先创建带FileFiled或者ImageFiled的Form: # In forms.py... from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField() 用Form处理: >>> f =UploadFileFormt(request.POST, request.FILES) view函数: from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from .forms import UploadFileForm def handle_uploaded_file(f): with open('some/file/name.txt', 'wb+') as destination: for chunk in f.chunks(): destination.write(chunk) def upload_file(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): handle_uploaded_file(request.FILES['file']) return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render_to_response('upload.html', {'form': form}) 使用Model处理上传文件 如果创建了一个带FileField或者ImageField域的Model,需要将上传文件存储到Model的FileFIeld域。 比如,使用nicEdit文本编辑器时,需要存储上传的文件,建立Model: from django.db import models class NicEditImage(models.Model): image = models.ImageField(upload_to='nicedit/%Y/%m/%d') 创建ModelForm: from django import forms class NicEditImageForm(forms.ModelForm): class Meta: model = NicEditImage view: def upload(request): if not request.user.is_authenticated(): json = simplejson.dumps({ 'success': False, 'errors': {'__all__': 'Authentication required'}}) return HttpResponse(json, mimetype='application/json') form = NicEditImageForm(request.POST or None, request.FILES or None) if form.is_valid(): image = form.save() #保存Form和Model json = simplejson.dumps({ 'success': True, 'upload': { 'links': { 'original': image.image.url}, 'image': { 'width': image.image.width, 'height': image.image.height} } }) else: json = simplejson.dumps({ 'success': False, 'errors': form.errors}) return HttpResponse(json, mimetype='application/json') 当然也可以手动存储文件到Model的文件域: from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import UploadFileForm from .models import ModelWithFileField def upload_file(request): if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): instance = ModelWithFileField(file_field=request.FILES['file']) #保存文件到FileField域 instance.save() return HttpResponseRedirect('/success/url/') else: form = UploadFileForm() return render(request, 'upload.html', {'form': form}) 不使用Form处理 想获得更大自由度时,可以全手动处理。 from django.db import models class Car(models.Model): name = models.CharField(max_length=255) price = models.DecimalField(max_digits=5, decimal_places=2) photo = models.ImageField(upload_to='cars') Model的FileField有以下属性: >>> car = Car.objects.get(name="57 Chevy") >>> car.photo <ImageFieldFile: chevy.jpg> >>> car.photo.name u'cars/chevy.jpg' >>> car.photo.path u'/media/cars/chevy.jpg' >>> car.photo.url u'http://media.example.com/cars/chevy.jpg' 可以手动修改文件的名称: >>> import os >>> from django.conf import settings >>> initial_path = car.photo.path >>> car.photo.name = 'cars/chevy_ii.jpg' >>> new_path = settings.MEDIA_ROOT + car.photo.name >>> # Move the file on the filesystem >>> os.rename(initial_path, new_path) >>> car.save() >>> car.photo.path '/media/cars/chevy_ii.jpg' >>> car.photo.path == new_path True Model的FileField是一个File对象,除了具有File对象的各种方法外,还有一个额外的save()方法: FieldFile.save(name, content, save=True)  name为存储名字,content为File或者File子类的实例 >>> car.photo.save('myphoto.jpg', content, save=False) >>> car.save() 类似于 >>> car.photo.save('myphoto.jpg', content, save=True) 手动存储: from django.core.files.base import ContentFile photo=request.FILES.get('photo','') if photo: file_content = ContentFile(photo.read()) #创建File对象 car.photo.save(photo.name, file_content) #保存文件到car的photo域 car.save() 一、简单文件上传实现 利用Django实现文件上传并且保存到指定路径下,其实并不困难,可以不需要用到django的forms,也不需要django的models,就可以简单实现上传功能。下面简单实现一下。 当Django在处理文件上传的时候,文件数据被保存在request.FILES。需要特别注意的是,只有当request方法是POST,且发送request的<form>有属性enctype=”multipart/form-data”时,表明不对字符进行编码,request.FILES中才会包含文件数据,否则request.FILES为空。 比如先写upload.html前面上传页面: # ./polls/templates/polls/upload.html<!DOCTYPE html><head> <meta charset="UTF-8"> <title>uploadFile</title></head><body> <form method="post" action="" enctype="multipart/form-data"> {% csrf_token %} <label> 上传文件 </label> <input type="file" name="myfile" /> <br/> <input type="submit" value="upload"/> </form></body></html> # ./polls/templates/polls/upload.html <!DOCTYPE html> <head> <meta charset="UTF-8"> <title>uploadFile</title> </head> <body> <form method="post" action="" enctype="multipart/form-data"> {% csrf_token %} <label> 上传文件 </label> <input type="file" name="myfile" /> <br/> <input type="submit" value="upload"/> </form> </body> </html> 然后写一个upload_file视图函数,处理文件上传,代码如下: # ./polls/viewsfrom django.shortcuts import renderfrom django.http import HttpResponsedef upload_file(request): # 请求方法为POST时,进行处理; if request.method == "POST": # 获取上传的文件,如果没有文件,则默认为None; File = request.FILES.get("myfile", None) if File is None: return HttpResponse("no files for upload!") else: # 打开特定的文件进行二进制的写操作; with open("/tmp/%s" % File.name, 'wb+') as f: # 分块写入文件; for chunk in File.chunks(): f.write(chunk) return HttpResponse("upload over!") else: return render(request, 'polls/upload.html') # ./polls/views from django.shortcuts import render from django.http import HttpResponse def upload_file(request): # 请求方法为POST时,进行处理; if request.method == "POST": # 获取上传的文件,如果没有文件,则默认为None; File = request.FILES.get("myfile", None) if File is None: return HttpResponse("no files for upload!") else: # 打开特定的文件进行二进制的写操作; with open("/tmp/%s" % File.name, 'wb+') as f: # 分块写入文件; for chunk in File.chunks(): f.write(chunk) return HttpResponse("upload over!") else: return render(request, 'polls/upload.html') 处理上传文件就是往服务器上生成一个文件,并将上传的文件内容写到新的文件中。然后写文件使用FILE.chunks()方法,而不是使用read()方法,能确保大文件并不会占用系统过多的内存。FILE方法和属性下面介绍。 最后写一个url匹配就可以了: # ./project_name/urls.pyurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^polls/', include('polls.urls'))]# ./polls/urls.pyfrom django.conf.urls import urlfrom . import viewsapp_name = 'polls'urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^upload/$', views.upload_file, name='upload_file'),] # ./project_name/urls.py urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^polls/', include('polls.urls')) ] # ./polls/urls.py from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.index, name='index'), url(r'^upload/$', views.upload_file, name='upload_file'), ] 最终效果如下图,选择文件就可以上传了: Django上传下载文件 那么这整个具体流程就是,访问http://10.10.0.109:8000/polls/upload/,调用upload_file函数,由于是GET请求,所以直接返回了upload.html页面,然后就可以进行POST请求上传文件了。 二、基于表单上传文件 在Django中我们可以采用Form类来处理表单,通过实例化处理和在模板中渲染,就可以轻松完成表单的需求,采用django的表单处理方式,能帮我们省去很多的工作,比如验证不能为空,或者要符合某种模式的输入才有效,这些处理起来非常方便,不用自己再单独写代码去验证表单的数据正确性,所以在开发中比较常用,Form提供了很多表单字段,比如日期,文本类型等,如果你熟悉基本的html,学起来会非常容易上手,下面只说下表单文件的上传,因为这个类型比较特殊,需要一点特殊的处理,我们来创建一个简单的一个实例: # ./polls/forms.pyfrom django import formsclass UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField() # ./polls/forms.py from django import forms class UploadFileForm(forms.Form): title = forms.CharField(max_length=50) file = forms.FileField() 这个表单就2个字段,要求用户title和上传一个文件或图片。 处理这个表单的视图会在request中接收到上传文件的数据。FILES是个字典,它包含每个FileField的键(或者ImageField,FileField的子类)。这样的话就可以用request.FILES[‘file’]来存放表单中的这些数据了。 注意request.FILES只有在请求方法为POST并且提交请求的<form>具有enctype=”multipart/form-data”属性时才包含数据。否则,request.FILES将为空。 大多数时候,你将只是简单地从request向表单中传递数据,就像Binding uploaded files to a form描述的那样。所以我们的视图处理逻辑基本类似下面这样: # polls/views.pyfrom django.shortcuts import renderfrom django.http import HttpResponsefrom polls.forms import UploadFileFormdef upload_file(request): if request.method == "POST": form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): handle_upload_file(request.FILES['file']) #handle_upload_file(form.files['file']) return HttpResponse('upload success!') else: form = UploadFileForm() return render(request, 'polls/upload.html', {'form': form}) # polls/views.py from django.shortcuts import render from django.http import HttpResponse from polls.forms import UploadFileForm def upload_file(request): if request.method == "POST": form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): handle_upload_file(request.FILES['file']) #handle_upload_file(form.files['file']) return HttpResponse('upload success!') else: form = UploadFileForm() return render(request, 'polls/upload.html', {'form': form}) 请注意,我们必须将request.FILES传递到form的构造函数中;这就是文件数据如何绑定到一个表单中。 这个函数判断用户的是否为POST请求,如果是并验证是有效的,然后就返回OK,在验证正确和返回OK的中间放我们的上传文件处理函数handle_upload_file,因为只有文件上传成功能返回OK。然后给这个handle_upload_file函数传递一个“request.FILES[‘file’]”,就是我们获取到的文件;也可以从表单中获取到,比如使用form提供的files或cleaned_data属性(form.files[‘file’]),这是表单提供的属性。如果是GET请求,就直接显示一个空表单,让用户输入。 注意我们必须向表单的构造器中传递request.FILES,这是文件数据绑定到表单的方法。FILES中的每个键为<input type=”file” name=”” />中的name。 然后写handle_upload_file函数,处理上传文件就是往服务器上生成一个文件,并将上传的文件内容写到新的文件中,所以它的基本函数是这样的,接收上传文件对象为参数,然后本地打开一个文件,从上传的文件中读出文件,写入新的文件中,代码如下: def handle_upload_file(file): with open("/tmp/%s" % file.name, 'wb+') as f: for chunk in file.chunks(): f.write(chunk) def handle_upload_file(file): with open("/tmp/%s" % file.name, 'wb+') as f: for chunk in file.chunks(): f.write(chunk) 接下来我们把form放到模板中去渲染,模板代码大概如下: # polls/templates/polls/upload.html<!DOCTYPE html><head> <meta charset="UTF-8"> <title>uploadFile</title></head><body> <form method="post" action="" enctype="multipart/form-data"> {% csrf_token %} {{ form }} <input type="submit" value="upload"/> </form></body></html> # polls/templates/polls/upload.html <!DOCTYPE html> <head> <meta charset="UTF-8"> <title>uploadFile</title> </head> <body> <form method="post" action="" enctype="multipart/form-data"> {% csrf_token %} {{ form }} <input type="submit" value="upload"/> </form> </body> </html> 这个表单被模板渲染后,看上去应该像下面这样,会生成静态源码: <label for="id_title">Title:</label><input type="text" name="title" id="id_title" required="" maxlength="50"><label for="id_file">File:</label><input type="file" name="file" id="id_file" required=""> <label for="id_title">Title:</label> <input type="text" name="title" id="id_title" required="" maxlength="50"> <label for="id_file">File:</label> <input type="file" name="file" id="id_file" required=""> 这样就完成了一个文件的上传,完毕。 上传数据在哪里储存? 在你保存上传文件之前,数据需要储存在某个地方。 通常,如果上传文件小于2.5MB,Django会把整个内容存到内存。这意味着,文件的保存仅仅涉及到从内存读取和写到磁盘,所以非常快。 但是,如果上传的文件很大,Django会把它写入一个临时文件,储存在你系统的临时目录中。在类Unix的平台下,你可以认为Django生成了一个文件,名称类似于/tmp/tmpzfp6I6.upload。如果上传的文件足够大,你可以观察到文件大小的增长,由于Django向磁盘写入数据。 这些特定值 – 2.5 MB,/tmp,以及其它 — 都仅仅是”合理的默认值”,它们可以自定义,这会在下一节中描述。 UploadedFile对象 在文件上传期间,实际文件数据存储在request.FILES中。此字典中的每个条目都是UploadedFile对象(或子类) – 上传文件的简单包装器。UploadedFile对象是对Python file对象的一个简单封装,并带有Django特定的附加功能。需要表示文件的时候,Django内部会使用这个类。UploadedFile对象拥有下列属性和方法: name 含有MEDIA_ROOT相对路径的文件名称。 size 文件的字节数。 mode 文件的读写模式。 open([mode=None]) 打开或者重新打开文件(同时会执行File.seek(0))。 mode参数的值和Python内建的open()相同。 重新打开一个文件时,无论文件原先以什么模式打开,mode都会覆盖;None的意思是以原先的模式重新打开。 read([num_bytes=None]) 读取文件内容。可选的size参数是要读的字节数;没有指定的话,文件会一直读到结尾。 __iter__() 迭代整个文件,并且每次生成一行。 File现在使用通用的换行符。以下字符会识别为换行符:Unix换行符’\n’,WIndows换行符’\r\n’,以及Macintosh旧式换行符\r。 chunks([chunk_size=None]) 迭代整个文件,并生成指定大小的一部分内容。chunk_size默认为64KB。 处理大文件时这会非常有用,因为这样可以把他们从磁盘中读取出来,而避免将整个文件存到内存中。 multiple_chunks([chunk_size=None]) 如果文件足够大,需要按照提供的chunk_size切分成几个部分来访问到所有内容,则返回True 。 write([content]) 将指定的内容字符串写到文件。取决于底层的储存系统,写入的内容在调用close()之前可能不会完全提交。 close() 关闭文件。 除了这些列出的方法,File沿用了file对象的以下属性和方法:encoding、fileno、flush、isatty、newlines、read、readinto、readlines、seek、softspace、tell、truncate、writelines、xreadlines。 基于这些属性和方法,我们把代码很轻松写的更规范,比如限制上传文件大小等。 三、文件下载 基于Django建立的网站,如果提供文件下载功能,最简单的方式莫过于将静态文件交给Nginx等处理,但有些时候,由于网站本身逻辑,需要通过Django提供下载功能,如页面数据导出功能(下载动态生成的文件)、先检查用户权限再下载文件等。因此,有必要研究一下文件下载功能在Django中的实现。 最简单的文件下载功能的实现 将文件流放入HttpResponse对象即可,如: def download_file(request): # do something... with open('/tmp/file_name.txt', 'rb') as f: c = f.read() return HttpResponse(c) def download_file(request): # do something... with open('/tmp/file_name.txt', 'rb') as f: c = f.read() return HttpResponse(c) 这种方式简单粗暴,适合小文件的下载,但如果这个文件非常大,这种方式会占用大量的内存,甚至导致服务器崩溃。 更合理的文件下载功能 Django的HttpResponse对象允许将迭代器作为传入参数,将上面代码中的传入参数c换成一个迭代器,便可以将上述下载功能优化为对大小文件均适合;而Django更进一步,推荐使用 StreamingHttpResponse对象取代HttpResponse对象,StreamingHttpResponse对象用于将文件流发送给浏览器,与HttpResponse对象非常相似,对于文件下载功能,使用StreamingHttpResponse对象更合理。 因此,更加合理的文件下载功能,应该先写一个迭代器,用于处理文件,然后将这个迭代器作为参数传递给StreaminghttpResponse对象,如: from django.http import StreamingHttpResponsedef download_file(request): def file_iterator(file, chunk_size=512): with open(file) as f: while True: c = f.read(chunk_size) if c: yield c else: break file = "file_name.txt" response = StreamingHttpResponse(file_iterator(file)) return response from django.http import StreamingHttpResponse def download_file(request): def file_iterator(file, chunk_size=512): with open(file) as f: while True: c = f.read(chunk_size) if c: yield c else: break file = "file_name.txt" response = StreamingHttpResponse(file_iterator(file)) return response 文件下载功能再次优化 上述的代码,已经完成了将服务器上的文件,通过文件流传输到浏览器,但文件流通常会以乱码形式显示到浏览器中,而非下载到硬盘上,因此,还要在做点优化,让文件流写入硬盘。优化很简单,给StreamingHttpResponse对象的Content-Type和Content-Disposition字段赋下面的值即可,如: response['Content-Type'] = 'application/octet-stream'response['Content-Disposition'] = 'attachment;filename="test.pdf"' response['Content-Type'] = 'application/octet-stream' response['Content-Disposition'] = 'attachment;filename="test.pdf"' 所以,完整代码如下: from django.http import StreamingHttpResponsedef download_file(request): def file_iterator(file, chunk_size=512): with open(file) as f: while True: c = f.read(chunk_size) if c: yield c else: break file = "big_file.pdf" response = StreamingHttpResponse(file_iterator(file)) response['Content-Type'] = 'application/octet-stream' response['Content-Disposition'] = 'attachment;filename="{0}"'.format(file) return response from django.http import StreamingHttpResponse def download_file(request): def file_iterator(file, chunk_size=512): with open(file) as f: while True: c = f.read(chunk_size) if c: yield c else: break file = "big_file.pdf" response = StreamingHttpResponse(file_iterator(file)) response['Content-Type'] = 'application/octet-stream' response['Content-Disposition'] = 'attachment;filename="{0}"'.format(file) return response Django 图片上传到数据库 并调用显示 环境:Django2.0 Python3.6.4 建立项目,数据库设置,就不说了。 直接上代码: 在models.py中,需要建立模型,这里使用了ImageField字段,用来存储图片路径,这个字段继承了FileField字段,本质上是一样的。这里Image.Field的默认max_length=100,我们可以根据需求自己指定。upload_to用于指定上传到哪个路径下。 PS: 使用ImageField首先需要装Pillow。 1 pip install Pillow 1 class Test(models.Model): 2 name = models.CharField(max_length=50) 3 image = models.ImageField(upload_to='logo') 4 def __str__(self): 5 return self.name 建立好模型,需要进行迁移操作, 1 python manage.py makemigrations 2 python manage.py migrate 在settings.py中,设置MEDIA_URL和MEDIA_ROOT MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 我们需要告诉Django,媒体文件的位置在哪里。这样就和数据库存储的路径相对应了,具体就是MEDIA_ROOT指定目录,upload_to就是在这个目录下进行操作。 1. 显示图片(图片调用)   为了能够方便录入数据,我们使用django后台管理,创建管理页面。 1 python manage.py createsuperuser   根据提示进行创建。在app下admin.py中将需要上面创建的模型进行添加。 1 admin.site.register(Test)    开启runserver,打开admin页面,就可以创建具体的数据了,将图片进行添加。   我们需要调用的话,需要在view.py中将数据进行传递。 img = Test.objects.all() return render(request, 'home.html', {'img':img})    在视图函数中加入,上面两句。在模板中,将图片展现出来: {% for i in img %} <img src="{{ MEDIA_URL }}{{ i.image }}"> {% endfor %}   这里{{ MEDIA_URL }}是必须要的,因为数据库取出来的地址是/logo/img001.png这种,路径不完整,我们存储的路径上/media/logo/img001.png    但到这里还是不能正常显示图片,会显示404,是因为图片的url也是需要通过django进行指派,我们还需要在urls.py进行设定。   为了html模板能正确找到MEDIA_URL,TEMPLATES中导入相关的包。 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'django.template.context_processors.media',#### add here ], }, }, ]     直接参考官方文档即可。这样图片的url才是完整的,我们的页面才可以正常显示图片。 2. 上传图片   我们可能需要用户上传自己的头像,或者相册,这里做一个简单的示范:   首先需要一个form,enctype="multipart/form-data" method="post" 是必须要填写的,表示数据不经过编码,直接上传。{%csrf_token%}也是post时,django强制要求的。 <form enctype="multipart/form-data" action="#" method="post"> {% csrf_token %} <input type="text" name="name"> <input type="file" name="logo"> <input type="submit" value="upload"> </form>   然后需要去views.py对视图函数进行操作。 if request.method == 'POST': file = request.FILES['logo'] if file: new_img = Test( name=request.POST.get('name'), image=file ) new_img.save()   与普通的数据不同,这里使用了request.FILES字典的方式去获取文件,然后创建新的数据,并保存到数据库中。

http://www.ywnds.com/?cat=38

https://yiyibooks.cn/xx/django_182/ref/forms/api.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券