[ecommerce2] 017 Image Uploads 圖片上傳
pillow安裝
pillow是python image庫
>pip install pillow
知識介紹
slug
slug:用於生成一個有意義(valid, meaninful)URL
參考(http://stackoverflow.com/questions/427102/what-is-a-slug-in-django)
比如:http://stackoverflow.com/questions/427102/what-is-a-slug-in-django 後面的“what-is-a-slug-in-django”就是經過slug後的產物
如何使用:
需要使用slugify功能:
from django.utils.text import slugify slugify(value)
If value is "Joel is a slug", the output will be "joel-is-a-slug".
It‘s a way of generating a valid URL, generally using data already obtained. For instance, using the title of an article to generate a URL. I‘d advise to generate the slug, using a function, given a title (or other piece of data), rather than setting it manually.
SlugField
也是起到類似作用,只不過這個一般是後臺直接添加時使用,比如:
slug = models.SlugField(unique=True)
這樣在後臺就有個slug框,填寫後,URL中就包含slug中的內容。
創建ProductImage類
class ProductImage(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to=image_upload_to)
def __unicode__(self):
return self.product.title
定義upload_to函數用於處理上傳圖片的保存,該函數需要接收兩個參數instance和filename
upload_to may also be a callable, such as a function. This will be called to obtain the upload path, including the filename. This callable must accept two arguments and return a Unix-style path (with forward slashes) to be passed along to the storage system. The two arguments are:
Argument |
Description |
instance |
An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached. In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field. |
filename |
The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path. |
入參instance和filename分別為
Product(iPhone Cover) iphone_cover.jpg
其中instance是當前上傳圖片關聯的product對象,filename為上傳文件的文件名
Upload_to函數返回文件系統存放路徑,一般路徑在
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_in_env", "media_root")
產品子目錄可以自定義
from django.utils.text import slugify def image_upload_to(instance, filename): title = instance.product.title slug = slugify(title) basename, file_extension = filename.split(".") new_filename = "%s-%s.%s" %(slug, instance.id, file_extension) return "products/%s/%s" %(slug, new_filename)
例子:將iphone_cover.jpg(Product Image)上傳給(Product)iPhone Cover
則title, slug, basename, file_extension, new_filename的值分別如下:
iPhone Cover iphone-cover iphone_cover jpg iphone-cover-2.jpg
註意同一文件重復上傳的結果,以MP3 Player為例,將mp3_player.jpg上傳給Product MP3 Player
如果是第一次創建ProductImage,instance.id為None
MP3 Player mp3-player mp3_player jpg mp3-player-None.jpg
MP3 Player mp3_player.jpg
同樣的名字,如果做第二次修改
MP3 Player mp3-player mp3_player jpg mp3-player-3.jpg
MP3 Player mp3_player.jpg
Currently: products/mp3-player/mp3-player-3.jpg
同樣的名字,如果繼續覆蓋,文件不會被覆蓋,而是增加隨機數重新拷貝一個
MP3 Player mp3-player mp3_player jpg mp3-player-3.jpg
MP3 Player mp3_player.jpg
Currently: products/mp3-player/mp3-player-3_7KveE47.jpg
執行migrate
>python manage.py makemigrations >python manage.py migrate
創建admin接口
from .models import Product,Variation,ProductImage admin.site.register(ProductImage)
在product_detail_view添加圖片顯示
下面這兩個的顯示分別如下
{{ img.image.file }}
{{ img.image.url }}
D:\virtualenv\ecommerce-ws\src\static_in_env\media_root\products\mp3-player\mp3-player-None.jpg
/media/products/mp3-player/mp3-player-None.jpg
MEDIA_URL = ‘/media/‘ MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), "static_in_env", "media_root")
[ecommerce2] 017 Image Uploads 圖片上傳