Django 简明教程

Django - File Uploading

web 应用程序通常需要能够上传文件(个人资料图片、歌曲、pdf、文字……)。让我们在本章讨论如何在上传文件。

It is generally useful for a web app to be able to upload files (profile picture, songs, pdf, words…​..). Let’s discuss how to upload files in this chapter.

Uploading an Image

在开始使用图像前,请确保你已安装了 Python 图像库 (PIL)。现在,为了说明如何上传图像,我们将在 myapp/forms.py 中创建一个个人资料表单 −

Before starting to play with an image, make sure you have the Python Image Library (PIL) installed. Now to illustrate uploading an image, let’s create a profile form, in our myapp/forms.py −

#-*- coding: utf-8 -*-
from django import forms

class ProfileForm(forms.Form):
   name = forms.CharField(max_length = 100)
   picture = forms.ImageFields()

正如你所见,这里的关键区别仅仅是 forms.ImageField 。ImageField 将确保上传的文件是图像。如果不是,表单验证将失败。

As you can see, the main difference here is just the forms.ImageField. ImageField will make sure the uploaded file is an image. If not, the form validation will fail.

现在,我们创建一个“个人资料”模型来保存我们上传的个人资料。这在 myapp/models.py 中完成 −

Now let’s create a "Profile" model to save our uploaded profile. This is done in myapp/models.py −

from django.db import models

class Profile(models.Model):
   name = models.CharField(max_length = 50)
   picture = models.ImageField(upload_to = 'pictures')

   class Meta:
      db_table = "profile"

正如你为模型所见,ImageField 需要必填参数 upload_to 。这代表你的图像将被保存到的硬盘驱动器位置。注意参数将被添加到在 settings.py 文件中定义的 MEDIA_ROOT 选项中。

As you can see for the model, the ImageField takes a compulsory argument: upload_to. This represents the place on the hard drive where your images will be saved. Note that the parameter will be added to the MEDIA_ROOT option defined in your settings.py file.

现在我们有了表单和模型,让我们在 myapp/views.py 中创建视图 −

Now that we have the Form and the Model, let’s create the view, in myapp/views.py −

#-*- coding: utf-8 -*-
from myapp.forms import ProfileForm
from myapp.models import Profile

def SaveProfile(request):
   saved = False

   if request.method == "POST":
      #Get the posted form
      MyProfileForm = ProfileForm(request.POST, request.FILES)

      if MyProfileForm.is_valid():
         profile = Profile()
         profile.name = MyProfileForm.cleaned_data["name"]
         profile.picture = MyProfileForm.cleaned_data["picture"]
         profile.save()
         saved = True
   else:
      MyProfileForm = Profileform()

   return render(request, 'saved.html', locals())

不要错过的部分是创建 ProfileForm 时有改动,我们增加了第二个参数 request.FILES 。如果没有通过表单验证,它将失败,并给出图片为空的消息。

The part not to miss is, there is a change when creating a ProfileForm, we added a second parameters: request.FILES. If not passed the form validation will fail, giving a message that says the picture is empty.

现在,我们只需要 saved.html 模板和 profile.html 模板,分别用于表单和重定向页面 −

Now, we just need the saved.html template and the profile.html template, for the form and the redirection page −

myapp/templates/saved.html

myapp/templates/saved.html

<html>
   <body>

      {% if saved %}
         <strong>Your profile was saved.</strong>
      {% endif %}

      {% if not saved %}
         <strong>Your profile was not saved.</strong>
      {% endif %}

   </body>
</html>

myapp/templates/profile.html

myapp/templates/profile.html

<html>
   <body>

      <form name = "form" enctype = "multipart/form-data"
         action = "{% url "myapp.views.SaveProfile" %}" method = "POST" >{% csrf_token %}

         <div style = "max-width:470px;">
            <center>
               <input type = "text" style = "margin-left:20%;"
               placeholder = "Name" name = "name" />
            </center>
         </div>

         <br>

         <div style = "max-width:470px;">
            <center>
               <input type = "file" style = "margin-left:20%;"
                  placeholder = "Picture" name = "picture" />
            </center>
         </div>

         <br>

         <div style = "max-width:470px;">
            <center>

               <button style = "border:0px;background-color:#4285F4; margin-top:8%;
                  height:35px; width:80%; margin-left:19%;" type = "submit" value = "Login" >
                  <strong>Login</strong>
               </button>

            </center>
         </div>

      </form>

   </body>
</html>

接下来,我们需要一对 URL 来开始:myapp/urls.py

Next, we need our pair of URLs to get started: myapp/urls.py

from django.conf.urls import patterns, url
from django.views.generic import TemplateView

urlpatterns = patterns(
   'myapp.views', url(r'^profile/',TemplateView.as_view(
      template_name = 'profile.html')), url(r'^saved/', 'SaveProfile', name = 'saved')
)

当访问“/myapp/profile”时,我们将得到以下呈现的 profile.html 模板 −

When accessing "/myapp/profile", we will get the following profile.html template rendered −

uploading image

在发布表单时,将渲染已保存的模板 −

And on form post, the saved template will be rendered −

form post template

我们有一个图像示例,但是,如果你想上传其他类型的文件,而不仅仅是图片,只需在 Model 和 Form 中用 FileField 替换 ImageField

We have a sample for image, but if you want to upload another type of file, not just image, just replace the ImageField in both Model and Form with FileField.