在Django 1.3中,用户上传一个“hello world”应用程序所需的最少示例代码是什么?


当前回答

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

它非常优雅,最重要的是,它提供了特色的js lib。Template不包含在服务器示例中,但是你可以在它的网站上找到demo。 精美上传:http://fineuploader.com/demos.html

django-fine-uploader

views.py

UploadView将post和delete请求分派给各自的处理程序。

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)

我也遇到过类似的问题,由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)

以亨利为例:

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函数。这将在文件系统中保存具有唯一名称的文件(以原始上传文件的文件名作为前缀),并返回所保存文件的完整路径。您可以将该路径保存在数据库中,稍后对该文件进行处理。

Demo

参见github repo,适用于Django 3

一个简单的Django文件上传示例

1. 创建一个django项目

运行startproject::

$ django-admin.py startproject sample

现在创建了一个文件夹(示例)。

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'到INSTALLED_APPS,并添加MEDIA_ROOT和MEDIA_URL,即::

INSTALLED_APPS = [
    'uploader',
    ...<other apps>...      
]

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.UploadView.as_view(), name='fileupload'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

5. 更新models.py

更新上传/ models.py::

from django.db import models
class Upload(models.Model):
    upload_file = models.FileField()    
    upload_date = models.DateTimeField(auto_now_add =True)

6. 更新views.py

更新上传/ views.py::

from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Upload
class UploadView(CreateView):
    model = Upload
    fields = ['upload_file', ]
    success_url = reverse_lazy('fileupload')
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['documents'] = Upload.objects.all()
        return context

7. 创建模板

创建文件夹sample/uploader/templates/uploader

创建文件upload_form.html ie sample/uploader/templates/uploader/upload_form.html::

<div style="padding:40px;margin:40px;border:1px solid #ccc">
    <h1>Django File Upload</h1>
    <form method="post" enctype="multipart/form-data">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit">Submit</button>
    </form><hr>
    <ul>
    {% for document in documents %}
        <li>
            <a href="{{ document.upload_file.url }}">{{ document.upload_file.name }}</a>
            <small>({{ document.upload_file.size|filesizeformat }}) - {{document.upload_date}}</small>
        </li>
    {% endfor %}
    </ul>
</div>

8. Syncronize数据库

同步数据库和runserver::

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

访问http://localhost: 8000 /

我必须说我发现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" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>

这些示例不是我的代码,它们是从我找到的其他两个示例中选取的。 我是一个相对初学者django,所以很可能我错过了一些关键点。