博客五部曲之一 - 简单博客
1499 浏览 5 years, 11 months
28 使用FileField和ImageField上传文件
版权声明: 转载请注明出处 http://www.codingsoho.com/FileField
我们首先用FileField来添加一个图片文件
首先在model里添加字段image为FileField。然后执行migrate,每次model有改动,都需要进行数据库migrate
class Post(models.Model):
title = models.CharField(max_length=120)
image = models.FileField(null=True, blank=True)
content = models.TextField()
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True, auto_now_add=False)
这个时候再打开admin,查看post,就可以看到里面多了一个字段image用来上传文件。这个时候可以开始上传文件,之前我们还需要设置一下media相关的配置,否则文件默认存放到根目录并且URL无法访问。
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR) , 'media_cdn')
跟STATIC,同样URL入口
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
再次上传文件car.jpg,文件会存放到media_cdn/car.jpg,URL为http://127.0.0.1:8000/media/car.jpg
如果要让用户上传文件,我们还需要修改一下模板和视图文件。
修改post_form.html,添加enctype以支持文件上传。
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<h1>Form</h1>
<form method="POST" enctype="multipart/form-data" action="">{% csrf_token %}
{{form.as_p}}
<input type="submit" class="btn btn-default" name="create post">
</form>
</div>
</div>
{% endblock content %}
修改post_create和post_update视图函数, form对象参数必须传入request.FILES
form = PostForm(request.POST or None, request.FILES or None, instance=instance)
同时,在form里加入image 字段
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
'title',
'image',
'content'
]
这样用户就可以在form表单里直接添加图片了。
最后,更新一下列表和详情视图,添加图片显示, 在标题上方加入
{% if object.image %}
<img src="{{object.image.url}}" class="img-responsive">
{% endif %}
ImageField
对于图片处理,Django有另外一个Field:ImageField,提供了更强大的功能。
https://docs.djangoproject.com/en/1.11/ref/models/fields/
要支持ImageField,需要安装依赖库 Pillow
首先修改image字段为ImageField,同时添加另外两个字段height_field和width_field
class Post(models.Model):
title = models.CharField(max_length=120)
image = models.ImageField(null=True, blank=True, width_field="width_field", height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
content = models.TextField()
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True, auto_now_add=False)
修改之后记得执行makemigrations和migrate
再次从admin打开post,可以看到heigh_field和with_field自动填进了当前图片的高度和宽度值。
新创建的图片也会自动填进这两个值,目前我们还不打算去用这两个值,但是在很多场合它们会非常有用处。
最后,我们通过函数自定义图片的上传路径
def upload_location(instance, filename):
return "%s/%s" % (instance.id, filename)
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=120)
image = models.ImageField(null=True, blank=True, width_field="width_field", height_field="height_field", upload_to=upload_location)
新的上传路径中,将会首先根据实例ID建一个目录,然后把图片放在下面。我们也可以修改图片的名字等,这个可以根据你的要求进行操作。