首页 文章

需要一个最小的Django文件上传示例[关闭]

提问于
浏览
600

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

10 回答

  • 1209

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

    要上传文件(在您的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)
    

    并在模板中使用该字段 .

  • 14

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

    它非常优雅,最重要的是,它提供了特色的js lib . 模板不包含在服务器示例中,但您可以在其网站上找到演示 . 精细上传者:http://fineuploader.com/demos.html

    django-fine-uploader

    views.py

    UploadView将发布和删除请求分派给各个处理程序 .

    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)
    
  • 10

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

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

    Update 2013-01-30: 除了1.3之外,GitHub的源代码还实现了Django 1.4 . 即使几乎没有变化,下面的教程对1.4也很有用 .

    Update 2013-05-10: 在GitHub上实现Django 1.5 . urls.py中重定向的微小更改以及list.html中url模板标记的使用 . 感谢hubert3的努力 .

    Update 2013-12-07: GangHub支持Django 1.6 . myapp / urls.py中的一个导入已更改 . 谢谢你到Arthedian .

    Update 2015-03-17: GangHub支持Django 1.7,感谢aronysidoro .

    Update 2015-09-04: GangHub支持Django 1.8,感谢nerogit .

    Update 2016-07-03: GangHub支持Django 1.9,感谢daavvenerogit

    项目树

    一个基本的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中,但它们是空的 . 有关详细信息,请参阅Django Managing Files中的第一行 . 记住还要设置数据库并将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的模型 . 该特定字段存储文件,例如至媒体/文件/ 2011/12/24 /基于当前日期和MEDIA_ROOT . 见FileField reference .

    # -*- 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

    要很好地处理上传,您需要一个表单 . 这个表单只有一个字段,但这就足够了 . 有关详细信息,请参阅Form FileField reference .

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

    Django默认不提供MEDIA_ROOT . 这在 生产环境 环境中会很危险 . 但在发展阶段,我们可以做空 . 注意最后一行 . 该行使Django能够从MEDIA_URL提供文件 . 这仅适用于开发阶段 .

    有关详细信息,请参阅django.conf.urls.static.static reference . 另见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 . 这里没什么特别的 .

    # -*- 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 . 有关详细信息,请参阅File Uploads documentation .

    FileField有许多可以在模板中使用的属性 . 例如 . 模板中的{}和{} . 在Using files in models articleThe 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 .

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

    结果

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

    我希望这个答案可以帮助我,就像它会帮助我一样 .

  • 55

    我必须说我发现django的文档令人困惑 . 另外,对于最简单的例子,为什么要提到表格?我在views.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" />
    
    <input type="submit" name="submit" value="Submit" /> </form>

    这些例子不是我的代码,它们来自我发现的另外两个例子 . 我是django的初学者,所以很可能是我遗漏了一些关键点 .

  • 9

    Henry's example上扩展:

    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 函数 . 这将在文件系统中使用唯一名称(带有原始上载文件的文件名)保存文件,并返回已保存文件的完整路径 . 您可以将路径保存在数据库中,稍后对该文件执行某些操作 .

  • 0

    演示

    更新Akseli Palén's answer . 看github repo,适用于Django 2

    最小的Django文件上传示例

    1.创建一个django项目

    运行startproject ::

    $ django-admin.py startproject sample
    

    现在创建了一个文件夹( sample )::

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

    2.创建一个应用程序

    创建一个应用::

    $ cd sample
    $ python manage.py startapp uploader
    

    现在创建了一个包含这些文件的文件夹( uploader )::

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

    3.更新settings.py

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

    INSTALLED_APPS = [
        ...<other apps>...
        'uploader.apps.UploaderConfig',
    ]
    
    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>...
        path('', 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.urls 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().order_by('-upload_date')
        return render(request,'home.html',{'form':img,'images':images})
    

    7.创建模板

    在文件夹 uploader 中创建一个文件夹 templates ,然后创建一个文件 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数据库

    Syncronize数据库和runserver ::

    $ python manage.py makemigrations
    $ python manage.py migrate
    $ python manage.py runserver
    

    访问http://localhost.com:8000

  • 60

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

    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 %}
    
  • 5

    不确定这种方法是否有任何缺点,但在views.py中更为简单:

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

    一般来说,当你试图“只是得到一个有效的例子”时,最好“开始编写代码” . 这里没有任何代码可以帮助您,因此它可以让我们更多地回答这个问题 .

    如果你想获取一个文件,你需要在html文件中的某个地方:

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

    这将为您提供浏览按钮,上传按钮以启动操作(提交表单)并记下enctype,以便Django知道给你 request.FILES

    在某个视图中,您可以使用以下方式访问该文件

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

    file upload docs中有大量信息

    我建议你彻底阅读页面,然后开始编写代码 - 然后在不起作用时返回示例和堆栈跟踪 .

  • 23

    我遇到了类似的问题,并由django管理站点解决 .

    # 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)
    

相关问题