这两天一直在琢磨django上传图片的做法,网上找到一堆资料都不行。
不过功夫不负有心人,我找啊找,终于发现了新大陆,找到一张老外的帖子,解决问题。
下面我们以一个例子来讲解一下这个过程。
1.首先要创建Photo的模型,比如:
class Photo(models.Model): item = models.ForeignKey(Item) title = models.CharField(max_length=100) image = ThumbnailImageField(upload_to=‘photos‘) caption = models.CharField(max_length=250, blank=True) slug = models.SlugField(max_length=40) class Meta: ordering = [‘title‘] def __unicode__(self): return self.title @permalink def get_absolute_url(self): return (‘photo_detail‘, None, {‘slug‘: self.slug})
这里还用到一个Item类和一个ThumbnailImageField类。Item类类似于专辑,收着好多图片;而ThumbnailImageField主要是用来展示缩略图的,在上传图片时不仅保存原文件,还保存一个缩略图副本。
class Item(models.Model): name = models.CharField(max_length=250) description = models.TextField() slug = models.SlugField(max_length=40) class Meta: ordering = [‘name‘] def __unicode__(self): return self.name @permalink def get_absolute_url(self): return (‘item_detail‘, None, {‘slug‘: self.slug})
class ThumbnailImageFieldFile(ImageFieldFile): def _get_thumb_path(self): return _add_thumb(self.path) thumb_path = property(_get_thumb_path) def _get_thumb_url(self): return _add_thumb(self.url) thumb_url = property(_get_thumb_url) def save(self, name, content, save=True): super(ThumbnailImageFieldFile, self).save(name, content, save) img = Image.open(self.path) img.thumbnail( (self.field.thumb_width, self.field.thumb_height), Image.ANTIALIAS ) print self.thumb_path print self.thumb_url img.save(self.thumb_path, ‘JPEG‘) def delete(self, save=True): if os.path.exists(self.thumb_path): os.remove(self.thumb_path) super(ThumbnailImageFieldFile, self).delete(save)
可以看到,在Photo里面Item是作为外码出现的,所以在上传图片时首先要有一个item。但是如果你想体验简单的上传图片的功能的话,把外码去掉或者把item属性去掉,然后适当改改下面的处理函数就OK了。
2.创建与模型相对应的PhotoForm
class PhotoForm(forms.Form): item = models.ForeignKey(Item) title = models.CharField(max_length=100) image = ThumbnailImageField(upload_to=‘photos‘) caption = models.CharField(max_length=250, blank=True) slug = models.SlugField(max_length=40)
3.在add_photo.html中创建一个表单form,加入要Photo模型对应的属性域:
<form action="/add_photo/" method="POST" enctype="multipart/form-data"> <div class="inline-group" id="photo_set-group"> <h2>Photos</h2> <div class="inline-related dynamic-photo_set" id="photo_set-0"> <h3> <b>Photo:</b> <span class="inline_label">#1</span> </h3> <fieldset class="module aligned "> <div class="form-row field-item"> <div> <label class="required" for="id_item">Item:</label> <select id="id_item" name="item"> <!-- 动态加载所有的item --> <option value="" selected="selected">---------</option> <option value="3">default</option> </select> </div> </div> <div class="form-row field-title"> <div> <label class="required" for="id_title">Title:</label> <input class="vTextField" id="id_title" maxlength="100" name="title" type="text"></div> </div> <div class="form-row field-image"> <div> <label class="required" for="id_image">Image:</label> <input id="id_image" name="image" type="file"></div> </div> <div class="form-row field-caption"> <div> <label for="id_caption">Caption:</label> <input class="vTextField" id="id_caption" maxlength="250" name="caption" type="text"></div> </div> <div class="form-row field-slug"> <div> <label class="required" for="id_slug">Slug:</label> <input class="vTextField" id="id_slug" maxlength="40" name="slug" type="text"></div> </div> </fieldset> <div class="submit-row"> <input type="submit" value="保存" class="default" name="_save"></div> </div> </div> </div> </form>
4.在views.py中添加处理函数,比如用户提交后就让add_photo()来处理
def add_photo(request): if request.method == ‘POST‘: # 往数据表中添加一行记录,并保存文件 form = PhotoForm(request.POST,request.FILES) if form.is_valid(): #往数据表中添加一行记录 item_id = request.POST[‘item‘] #获取item的id值 title = request.POST[‘title‘] caption = request.POST[‘caption‘] slug = request.POST[‘slug‘] image = ‘photos/%s‘ % request.FILES[‘image‘] photo = Photo(item_id=item_id, title=title, image=image, caption=caption, slug=slug) photo.save() # 保存文件到本地计算机 obj = Photo.objects.get(id=item_id) file_content = ContentFile(request.FILES[‘image‘].read()) obj.image.save(request.FILES[‘image‘].name, file_content) return HttpResponseRedirect(‘/gallery/items/‘) else: return render_to_response(‘add_photo.html‘)
这样就算大功告成了。
原文:http://blog.csdn.net/whoami021/article/details/23097811