如何在 Django 中上传文件? [英] How to upload a file in Django?

查看:33
本文介绍了如何在 Django 中上传文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为 Django 的新手,我很难在 Django 1.3 中制作上传应用程序.我找不到任何最新的示例/片段.有人可以发布一个最小但完整的(模型、视图、模板)示例代码吗?

As a newbie to Django, I am having difficulty making an upload app in Django 1.3. I could not find any up-to-date example/snippets. May someone post a minimal but complete (Model, View, Template) example code to do so?

推荐答案

呸,Django 文档确实没有很好的例子.我花了 2 个多小时来挖掘所有部分以了解这是如何工作的.有了这些知识,我实现了一个项目,可以上传文件并将它们显示为列表.要下载项目的源代码,请访问 https://github.com/axelpale/minimal-django-file-upload-example 或克隆它:

Phew, Django documentation really does not have good example about this. I spent over 2 hours to dig up all the pieces to understand how this works. With that knowledge I implemented a project that makes possible to upload files and show them as list. To download source for the project, visit https://github.com/axelpale/minimal-django-file-upload-example or clone it:

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

更新 2013-01-30: GitHub 上的源代码除了 1.3 之外,还实现了 Django 1.4.尽管更改很少,但以下教程对 1.4 也很有用.

Update 2013-01-30: The source at GitHub has also implementation for Django 1.4 in addition to 1.3. Even though there is few changes the following tutorial is also useful for 1.4.

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

Update 2013-05-10: Implementation for Django 1.5 at GitHub. Minor changes in redirection in urls.py and usage of url template tag in list.html. Thanks to hubert3 for the effort.

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

Update 2013-12-07: Django 1.6 supported at GitHub. One import changed in myapp/urls.py. Thanks goes to Arthedian.

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

Update 2015-03-17: Django 1.7 supported at GitHub, thanks to aronysidoro.

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

Update 2015-09-04: Django 1.8 supported at GitHub, thanks to nerogit.

更新 2016-07-03: GitHub 支持 Django 1.9,感谢 daavvenerogit

Update 2016-07-03: Django 1.9 supported at GitHub, thanks to daavve and nerogit

一个基本的 Django 1.3 项目,带有单个应用程序和用于上传的 media/目录.

A basic Django 1.3 project with single app and media/ directory for uploads.

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 中,但它们是空的.有关详细信息,请参阅 Django 管理文件 中的第一行.记住还要设置数据库并将myapp添加到INSTALLED_APPS

1. Settings: myproject/settings.py

To upload and serve files, you need to specify where Django stores uploaded files and from what URL Django serves them. MEDIA_ROOT and MEDIA_URL are in settings.py by default but they are empty. See the first lines in Django Managing Files for details. Remember also set the database and add myapp to 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 的模型.这个特定的字段存储文件,例如到 media/documents/2011/12/24/基于当前日期和 MEDIA_ROOT.请参阅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

要很好地处理上传,您需要一个表单.此表单只有一个字段,但这已经足够了.有关详细信息,请参阅表单文件字段参考.

# -*- 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() 自动处理文件到文件系统的存储.

4. View: myproject/myapp/views.py

A view where all the magic happens. Pay attention how request.FILES are handled. For me, it was really hard to spot the fact that request.FILES['docfile'] can be saved to models.FileField just like that. The model's save() handles the storing of the file to the filesystem automatically.

# -*- 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.项目网址:myproject/urls.py

Django 默认不提供 MEDIA_ROOT 服务.这在生产环境中会很危险.但在开发阶段,我们可以缩短.注意最后一行.该行使 Django 能够从 MEDIA_URL 提供文件.这仅在开发阶段有效.

5. Project URLs: myproject/urls.py

Django does not serve MEDIA_ROOT by default. That would be dangerous in production environment. But in development stage, we could cut short. Pay attention to the last line. That line enables Django to serve files from MEDIA_URL. This works only in developement stage.

参见 django.conf.urls.static.static 参考了解详情.另见关于服务的讨论媒体文件.

See django.conf.urls.static.static reference for details. See also this discussion about serving media files.

# -*- 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.应用网址:myproject/myapp/urls.py

要使视图可访问,您必须为其指定 url.这里没什么特别的.

6. App URLs: myproject/myapp/urls.py

To make the view accessible, you must specify urls for it. Nothing special here.

# -*- 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 }} 与模板中的一样.在在模型中使用文件一文文件对象文档.

The FileField has many attributes that can be used in templates. E.g. {{ document.docfile.url }} and {{ document.docfile.name }} as in the template. See more about these in Using files in models article and The File object documentation.

<!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.

8. Initialize

Just run syncdb and runserver.

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

结果

终于,一切准备就绪.在默认的 Django 开发环境中,可以在 localhost:8000/list/ 看到上传的文档列表.今天文件上传到/path/to/myproject/media/documents/2011/12/17/,可以从列表中打开.

Results

Finally, everything is ready. On default Django developement environment the list of uploaded documents can be seen at localhost:8000/list/. Today the files are uploaded to /path/to/myproject/media/documents/2011/12/17/ and can be opened from the list.

我希望这个答案能帮助别人,就像它对我的帮助一样.

I hope this answer will help someone as much as it would have helped me.

这篇关于如何在 Django 中上传文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆