最近在学习python世界强大的web开发框架–Django.
在官网(https://www.djangoproject.com/)中大致了解了下,再跟着《Django Web开发指南》这本书做些简单的应用。
先是第7章Photo Gallery应用,本来以为按图索骥很简单就可以过去,没想到还是碰到了坑。
书里面有些内容没有提到,即便我去下载例子源码(http://withdjango.com/readers/),由于本地使用的环境与作者当时的不一样,也不容易解决。
还是先说下问题吧。
该应用主要在后台上传图片,管理图片,在前端显示图片及缩略图。
按django开发基本流程,创建项目Gallery,创建应用items, 接着定义模型Item和Photo:
@/Gallery/items/models.py
from django.db import models
from django.db.models import permalink
from django.contrib import admin
class Item(models.Model):
name = models.CharField(max_length=250)
description = models.TextField()
class Meta:
ordering = ['name']
def __unicode__(self):
return self.name
@permalink
def get_absolute_url(self):
return ('item_detail',None,{'object_id':self.id})
class Photo(models.Model):
item = models.ForeignKey(Item)
title = models.CharField(max_length=100)
#图片上传到photos目录下
image = ImageField(upload_to='photos')
caption = models.CharField(max_length=250,blank=True)
class Meta:
ordering = ['title']
def __unicode__(self):
return self.title
@permalink
def get_absolute_url(self):
return ('photo_detail', None, {'object_id': self.id})
class PhotoInline(admin.StackedInline):
model = Photo
class ItemAdmin(admin.ModelAdmin):
inlines = [PhotoInline]
admin.site.register(Item,ItemAdmin)
admin.site.register(Photo)
再按照书中所说,在settings.py定义MEDIA_ROOT,用于设置上传文件保存的路径,我这里设为 ‘/res/images/’。
安装PIL,确保ImageFiled可以使用。
然后就是创建数据库了:python manage.py syncdb
syncdb是针对旧版本,我本地安装的django是1.8版本,创建数据库需要以下2个命令:
创建数据库迁移记录:python manage.py makemigrations items
执行数据库语句:python manage.py migrate
启动服务器 python manage.py runserver
打开后台管理页面 http://localhost:8000/admin/
创建一条item,并上传图片,save成功!
打开该item,点击刚刚上传的图片链接,结果与书中正常情况不一样,我这里提示错误:
Request Method: GET
Request URL: http://localhost:8000/admin/items/item/3/photos/1.jpg/
Raised by: django.contrib.admin.options.change_view
点击图片后显示的路径不是MEDIA_ROOT下面的,而是当前路径 (http://localhost:8000/admin/items/item/3/)加上 photos/1.jpg
查找例子源码,在setting中加上如下配置:
ROOT_URL = ‘/’
MEDIA_URL = ROOT_URL + ‘media/’
错误内容变成:
Request Method: GET
Request URL: http://localhost:8000/media/photos/1_nmyyTll.jpg
说明打开图片的链接依赖于MEDIA_URL的设置。
但是上传图片保存在哪里了呢?是否有被保存成功?
于是编写ImageField的子类ThumbnailImageFieldFile,重写save方法,在里面打印文件路径:
ThumbnailImageFieldFile, save image path:D:\res\images\photos\1_FmCeypX.jpg
原来文件没有被保存到项目目录下,而是在D盘!为什么是D盘?也许是项目根目录在D盘吧。。。
需要解决以下问题:
1.图片保存路径需要和点击时链接路径一致
2.本地环境中,图片保存路径需要设置在项目目录下才能访问
根据以上结果可知:
保存图片的完整路径为 base_path + MEDIA_ROOT + upload_to设置的路径 + 文件名
而点击图片时链接路径为 context_path + MEDIA_URL + upload_to设置的路径 + 文件名
更改 MEDIA_ROOT = BASE_DIR + ‘/res/images/’
其中 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))为当前文件路径。
于是文件保存路径成功更改为项目中的路径:
save image path:D:\Code\Python\Project\Gallery\res\images\photos\111_Grn3cLo.jpg
再更改 MEDIA_URL = ROOT_URL + ‘res/images/’
文件链接路径 http://localhost:8000/res/images/photos/111_Grn3cLo.jpg
两者终于一致了,在admin后台打开图片,与之前错误提示说路径不匹配不同,这次是提示找不到文件,应该是访问静态文件没有相应配置造成。
确认setting.py中INSTALLED_APPS已经加入’django.contrib.staticfiles’, STATIC_URL = ‘/res/’ 也已经设置,还是不能访问图片。
查看官网说明 https://docs.djangoproject.com/en/1.8/howto/static-files/
加入配置:
STATICFILES_DIRS = (
os.path.join(BASE_DIR, “res”),
)
让django框架在该目录列表中寻找静态文件,此时图片可以成功访问!