需要一个最小的Djangofile upload的例子

作为Django的新手,我很难在Django 1.3上做一个上传应用程序。 我找不到任何最新的示例/片段。 有人可能会发布一个最小但完整的(模型,视图,模板)示例代码来做到这一点?

嘿嘿,Django的文档实在没有这个好例子。 我花了2个多小时挖掘所有的东西,以了解这是如何工作的。 有了这些知识,我实现了一个项目,使上传文件和列表显示。 要下载该项目的源代码,请访问https://github.com/axelpale/minimal-django-file-upload-example或克隆它:;

> git clone https://github.com/axelpale/minimal-django-file-upload-example.git 

更新2013年1月30日:在GitHub的源还有除了1.3以外的Django 1.4的实现。 即使几乎没有变化,以下教程也适用于1.4。

更新2013-05-10:在GitHub上实现Django 1.5。 在urls.py中redirect的细微变化和在list.html中使用url模板标签。 感谢hubert3的努力。

更新2013-12-07:在GitHub上支持Django 1.6。 在myapp / urls.py中更改了一个导入。 谢谢去Arthedian 。

更新2015-03-17: Django 1.7支持GitHub,感谢aronysidoro 。

更新2015-09-04: Django 1.8支持GitHub,感谢nerogit 。

更新2016-07-03:在GitHub上支持Django 1.9,感谢daavve和nerogit

项目树

一个基本的Django 1.3项目,具有单一的应用程序和媒体/目录上传。

 minimal-django-file-upload-example/ src/ myproject/ database/ sqlite.db media/ myapp/ templates/ myapp/ list.html forms.py models.py urls.py views.py __init__.py manage.py settings.py urls.py 

1.设置:myproject / settings.py

要上传和提供文件,您需要指定Django存储上传文件的位置以及Django为其提供服务的URL。 MEDIA_ROOT和MEDIA_URL默认在settings.py中,但是它们是空的。 有关详细信息,请参阅“ Djangopipe理文件”中的第一行。 还记得设置数据库并将myapp添加到INSTALLED_APPS

 ... import os BASE_DIR = os.path.dirname(os.path.dirname(__file__)) ... DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'database.sqlite3'), 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } } ... MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' ... INSTALLED_APPS = ( ... 'myapp', ) 

2.型号:myproject / myapp / models.py

接下来,您需要一个带有FileField的模型。 这个特定的字段根据当前date和MEDIA_ROOT将文件存储到例如media / documents / 2011/12/24 /。 请参阅FileField参考 。

 # -*- coding: utf-8 -*- from django.db import models class Document(models.Model): docfile = models.FileField(upload_to='documents/%Y/%m/%d') 

3.窗体:myproject / myapp / forms.py

为了处理上传,你需要一个表单。 这种forms只有一个领域,但这已经足够了。 有关详细信息,请参阅FormFieldField参考 。

 # -*- coding: utf-8 -*- from django import forms class DocumentForm(forms.Form): docfile = forms.FileField( label='Select a file', help_text='max. 42 megabytes' ) 

4.查看:myproject / myapp / views.py

一个观点,所有的魔法发生。 注意request.FILES是如何处理的。 对我来说,真的很难发现request.FILES['docfile']可以保存到models.FileField的事实。 模型的save()处理文件自动存储到文件系统。

 # -*- coding: utf-8 -*- from django.shortcuts import render_to_response from django.template import RequestContext from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from myproject.myapp.models import Document from myproject.myapp.forms import DocumentForm def list(request): # Handle file upload if request.method == 'POST': form = DocumentForm(request.POST, request.FILES) if form.is_valid(): newdoc = Document(docfile = request.FILES['docfile']) newdoc.save() # Redirect to the document list after POST return HttpResponseRedirect(reverse('myapp.views.list')) else: form = DocumentForm() # A empty, unbound form # Load documents for the list page documents = Document.objects.all() # Render list page with the documents and the form return render_to_response( 'myapp/list.html', {'documents': documents, 'form': form}, context_instance=RequestContext(request) ) 

5.项目URL:myproject / urls.py

Django默认不提供MEDIA_ROOT。 这在生产环境中会很危险。 但在发展阶段,我们可以缩短。 注意最后一行。 该行允许Django从MEDIA_URL提供文件。 这只适用于发展阶段。

有关详细信息,请参阅django.conf.urls.static.static参考 。 另请参阅关于服务媒体文件的讨论 。

 # -*- coding: utf-8 -*- from django.conf.urls import patterns, include, url from django.conf import settings from django.conf.urls.static import static urlpatterns = patterns('', (r'^', include('myapp.urls')), ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 

6.应用程序URL:myproject / myapp / urls.py

为了使视图可以访问,你必须指定它的URL。 这里没什么特别的

 # -*- coding: utf-8 -*- from django.conf.urls import patterns, url urlpatterns = patterns('myapp.views', url(r'^list/$', 'list', name='list'), ) 

7.模板:myproject / myapp / templates / myapp / list.html

最后一部分:列表模板和下面的上传表单。 表单必须将enctype-attribute设置为“multipart / form-data”,并将方法设置为“post”以使上传到Django成为可能。 有关详细信息,请参阅文件上载文档

FileField有许多可以在模板中使用的属性。 例如{{document.docfile.url}}和{{document.docfile.name}}。 在模型文章和文件对象文档中使用文件可以查看更多关于这些的信息 。

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Minimal Django File Upload Example</title> </head> <body> <!-- List of uploaded documents --> {% if documents %} <ul> {% for document in documents %} <li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li> {% endfor %} </ul> {% else %} <p>No documents.</p> {% endif %} <!-- Upload form. Note enctype attribute! --> <form action="{% url 'list' %}" method="post" enctype="multipart/form-data"> {% csrf_token %} <p>{{ form.non_field_errors }}</p> <p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p> <p> {{ form.docfile.errors }} {{ form.docfile }} </p> <p><input type="submit" value="Upload" /></p> </form> </body> </html> 

8.初始化

只需运行syncdb和runserver。

 > cd myproject > python manage.py syncdb > python manage.py runserver 

结果

最后,一切都准备好了。 在默认的Django开发环境中,可以在localhost:8000/list/看到上传文件的localhost:8000/list/ 。 今天,文件被上传到/ path / to / myproject / media / documents / 2011/12/17 /,并可以从列表中打开。

我希望这个答案能够帮助别人,就像帮助我一样。

一般来说,当你试图“只是一个工作的例子”时,最好是“开始编写代码”。 这里没有任何代码可以帮助你,所以它使我们回答更多的问题。

如果你想抓取一个文件,你需要在某个html文件中这样的东西:

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

这会给你浏览button,一个上传button来启动行动(提交表单),并注意这个Django知道给你request.FILES

在某个地方你可以访问该文件

 def myview(request): request.FILES['myfile'] # this is my file 

file upload文档中有大量的信息

我build议你仔细阅读这个页面,然后开始编写代码 – 然后在不工作的时候返回示例和堆栈跟踪。

AkseliPalén的回答更新。 看到github回购 ,与Django 1.11合作

一个最小的Djangofile upload的例子

1.创build一个django项目

运行startproject ::

 $ django-admin.py startproject sample 

现在创build一个文件夹( 样本 )::

 sample/ manage.py sample/ __init__.py settings.py urls.py wsgi.py 

2.创build一个应用程序

创build应用程序::

 python manage.py startapp uploader 

现在创build了这些文件的文件夹( uploader ):

 uploader/ __init__.py admin.py app.py models.py tests.py views.py migrations/ __init__.py 

3.更新settings.py

sample/settings.py添加'uploader'INSTALLED_APPS并添加MEDIA_ROOTMEDIA_URL ,即::

 INSTALLED_APPS = ( ...<other apps>... 'uploader', ) MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/' 

4.更新urls.py

sample/urls.py添加::

 ...<other imports>... from django.conf import settings from django.conf.urls.static import static from uploader import views as uploader_views urlpatterns = [ ...<other url patterns>... url(r'^upload/$', uploader_views.home, name='imageupload'), ]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 

5.更新models.py

更新uploader/models.py ::

 from django.db import models from django.forms import ModelForm class Upload(models.Model): pic = models.FileField(upload_to="images/") upload_date=models.DateTimeField(auto_now_add =True) # FileUpload form class. class UploadForm(ModelForm): class Meta: model = Upload fields = ('pic',) 

6.更新views.py

更新uploader/views.py ::

 from django.shortcuts import render from uploader.models import UploadForm,Upload from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse # Create your views here. def home(request): if request.method=="POST": img = UploadForm(request.POST, request.FILES) if img.is_valid(): img.save() return HttpResponseRedirect(reverse('imageupload')) else: img=UploadForm() images=Upload.objects.all() return render(request,'home.html',{'form':img,'images':images}) 

7.创build模板

在文件夹uploader中创build一个文件夹模板 ,然后创build一个文件home.html ,即sample/uploader/templates/home.html ::

 <div style="padding:40px;margin:40px;border:1px solid #ccc"> <h1>picture</h1> <form action="#" method="post" enctype="multipart/form-data"> {% csrf_token %} {{form}} <input type="submit" value="Upload" /> </form> {% for img in images %} {{forloop.counter}}.<a href="{{ img.pic.url }}">{{ img.pic.name }}</a> ({{img.upload_date}})<hr /> {% endfor %} </div> 

8.同步数据库

Syncronize数据库和runserver ::

 $ python manage.py makemigrations $ python manage.py migrate $ python manage.py runserver visit <http://localhost.com:8000/upload> 

我必须说我发现在Django的文件混淆。 也是最简单的例子,为什么forms被提及? 我在view.py中工作的例子是:

 for key, file in request.FILES.items(): path = file.name dest = open(path, 'w') if file.multiple_chunks: for c in file.chunks(): dest.write(c) else: dest.write(file.read()) dest.close() 

该html文件看起来像下面的代码,虽然这个例子只上传一个文件,保存文件的代码处理很多:

 <form action="/upload_file/" method="post" enctype="multipart/form-data">{% csrf_token %} <label for="file">Filename:</label> <input type="file" name="file" id="file" /> <br /> <input type="submit" name="submit" value="Submit" /> </form> 

这些例子不是我的代码,它们是从我发现的另外两个例子中得到的。 我是一个django的相对初学者,所以很可能我错过了一些关键点。

继续亨利的例子 :

 import tempfile import shutil FILE_UPLOAD_DIR = '/home/imran/uploads' def handle_uploaded_file(source): fd, filepath = tempfile.mkstemp(prefix=source.name, dir=FILE_UPLOAD_DIR) with open(filepath, 'wb') as dest: shutil.copyfileobj(source, dest) return filepath 

您可以使用上传的文件对象在视图中调用此handle_uploaded_file函数。 这将在文件系统中以一个唯一的名称(以原始上传文件的文件名作为前缀)保存文件,并返回保存文件的完整path。 您可以将path保存在数据库中,稍后使用该文件进行操作。

在这里它可以帮助你:在你的models.py中创build一个文件字段

上传文件(在你的admin.py中):

 def save_model(self, request, obj, form, change): url = "http://img.youtube.com/vi/%s/hqdefault.jpg" %(obj.video) url = str(url) if url: temp_img = NamedTemporaryFile(delete=True) temp_img.write(urllib2.urlopen(url).read()) temp_img.flush() filename_img = urlparse(url).path.split('/')[-1] obj.image.save(filename_img,File(temp_img) 

并在您的模板中也使用该字段。

我也有类似的要求。 networking上的大多数例子都是要求创build模型,并创build我不想使用的表单。 这是我的最终代码。

 if request.method == 'POST': file1 = request.FILES['file'] contentOfFile = file1.read() if file1: return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile}) 

而在HTML上传我写道:

 {% block content %} <h1>File content</h1> <form action="{% url 'blogapp:uploadComplete'%}" method="post" enctype="multipart/form-data"> {% csrf_token %} <input id="uploadbutton" type="file" value="Browse" name="file" accept="text/csv" /> <input type="submit" value="Upload" /> </form> {% endblock %} 

以下是显示文件内容的HTML:

 {% block content %} <h3>File uploaded successfully</h3> {{file.name}} </br>content = {{contentOfFile}} {% endblock %} 

您可以参考Fine Uploader中的服务器示例,其中有Django版本。 https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader

这是非常优雅,最重要的是,它提供了特色的js库。 服务器示例中不包含模板,但您可以在其网站上find示例。 美好的上传者: http : //fineuploader.com/demos.html

Django的精细上传

views.py

UploadView发送post并删除请求到各自的处理程序。

 class UploadView(View): @csrf_exempt def dispatch(self, *args, **kwargs): return super(UploadView, self).dispatch(*args, **kwargs) def post(self, request, *args, **kwargs): """A POST request. Validate the form and then handle the upload based ont the POSTed data. Does not handle extra parameters yet. """ form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): handle_upload(request.FILES['qqfile'], form.cleaned_data) return make_response(content=json.dumps({ 'success': True })) else: return make_response(status=400, content=json.dumps({ 'success': False, 'error': '%s' % repr(form.errors) })) def delete(self, request, *args, **kwargs): """A DELETE request. If found, deletes a file with the corresponding UUID from the server's filesystem. """ qquuid = kwargs.get('qquuid', '') if qquuid: try: handle_deleted_file(qquuid) return make_response(content=json.dumps({ 'success': True })) except Exception, e: return make_response(status=400, content=json.dumps({ 'success': False, 'error': '%s' % repr(e) })) return make_response(status=404, content=json.dumps({ 'success': False, 'error': 'File not present' })) 

forms.py

 class UploadFileForm(forms.Form): """ This form represents a basic request from Fine Uploader. The required fields will **always** be sent, the other fields are optional based on your setup. Edit this if you want to add custom parameters in the body of the POST request. """ qqfile = forms.FileField() qquuid = forms.CharField() qqfilename = forms.CharField() qqpartindex = forms.IntegerField(required=False) qqchunksize = forms.IntegerField(required=False) qqpartbyteoffset = forms.IntegerField(required=False) qqtotalfilesize = forms.IntegerField(required=False) qqtotalparts = forms.IntegerField(required=False) 

不知道这种方法是否有任何缺点,但在views.py中更是微乎其微:

 entry = form.save() # save uploaded file if request.FILES['myfile']: entry.myfile.save(request.FILES['myfile']._name, request.FILES['myfile'], True) 

我遇到类似的问题,并由djangopipe理站点解决。

 # models class Document(models.Model): docfile = models.FileField(upload_to='documents/Temp/%Y/%m/%d') def doc_name(self): return self.docfile.name.split('/')[-1] # only the name, not full path # admin from myapp.models import Document class DocumentAdmin(admin.ModelAdmin): list_display = ('doc_name',) admin.site.register(Document, DocumentAdmin)