One thing that I see the need for on almost every site is a place to put images. Whether it’s a band website, a personal homepage, or a school newspaper, there will be a need for a photo gallery. The easy way to do that is to use an open source package available already like Gallery2. But that’s written in PHP and it won’t integrate easily with the rest of your site–especially if you use Django as the framework for the rest of your site.
The solution: write a gallery application for use in your website. At first it may seem like a daunting task to create, but as I’ve found out, it can be quite easy. My implementation is not completely up and running yet, but that’s due to design issues with the rest of the site, not the photo gallery app itself. With no further adieu, let’s dive in and see how this can work.
class Album(models.Model):
name = models.CharField(maxlength=128)
slug = models.SlugField(prepopulate_from=("name",))
summary = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
As you can see, this is the Album object which contains information about a set of associated photos. But wait, we don’t have photos created yet! Let’s do that now.
class Photo(models.Model):
title = models.CharField(maxlength=256)
summary = models.TextField(blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
image = models.ImageField(upload_to='photos/%Y/%m')
album = models.ForeignKey(Album)
is_cover_photo = models.BooleanField()
Ok so now we have albums which have photos, and photos have a lot of information like a file which contains an image, a title, and a summary.
Now that we have these objects, we have some choices to make. The images need to be resized into medium and small images for display on the list and detail pages, respectively. This can be done several ways:
Use the HTML width and height attributes to resize the images.
Create a Django view with width and height parameters to both resize and serve the images. (Lazy computation)
Resize the images on upload and store them to disk. (Upfront computation)
The first way is not optimal for two reasons. Firstly each picture must be downloaded in it’s entirety. This is inefficient and could upset people with less bandwidth or bandwidth limits. Secondly, when most browsers resize images, they do so using poor quality filters, resulting in a low quality representation of an image.
The second way is the most flexible, since the height and the width can be changed in a template or in a view and the resized images will change accordingly. However, there is more on-the-fly computation with this way, possibly increasing page load times. Also, Django is not designed to be used to serve binary files directly, so there could be unforseen consequences with handling a large number of photos this way.
The third way is less flexible, but it has one key advantage: it’s fast. Since the computation is done on upload, Apache or any other http media server can be used instead, completely removing the need to use the Django framework at all. Let’s implement it this way.
First, we’ll need to overload the save function of the Photo model:
def save(self):
if self.is_cover_photo:
other_cover_photo = Photo.objects.filter(album=self.album).filter(is_cover_photo = True)
for photo in other_cover_photo:
photo.is_cover_photo = False
photo.save()
filename = self.get_image_filename()
if not filename == '':
img = Image.open(filename)
img.thumbnail((512,512), Image.ANTIALIAS)
img.save(self.get_medium_filename())
img.thumbnail((150,150), Image.ANTIALIAS)
img.save(self.get_small_filename())
super(Photo, self).save()
Before I talk about the thumbnailing aspect of this function, I’d like to briefly explain what’s going on with the cover_photo aspect of Photo objects. Each Album has a cover photo, so if the Album needs to be represented, it can be represented by one special photo. This is just part of the way that I have designed my object, and can easily be removed. However, there is a small bit of obligatory boilerplate code in this save function which sets any other is_cover_photo attributes to False if necessary. (There can only be one cover photo per album, after all). I’ll come back to dealing with cover photos later.
First off, the if not filename == ” statement is needed because save is sometimes called with no image data, and that can and will throw exceptions if PIL is used on a None object. Then, it resizes a medium-sized (512px by 512px) image and saves it to a location provided by get_medium_filename. I leave it to you to define your own get_medium_filename and get_small_filename with your own naming convention. I followed Flickr’s example of an underscore followed by an argument (image001.jpg becomes image001_m.jpg for medium and image001_s.jpg for small). Finally, this method must call the it’s parent save method so that all of the other attributes are saved correctly.
Now that we’ve overloaded the save functionality, we are going to have a problem with deletion. Django will automatically delete the original image, but the resized thumbnails will be left on the disk forever. This is not a huge problem, but we don’t want that to happen anyways. So let’s take care of that by also overloading the delete function of Photo’s model:
def delete(self):
filename = self.get_image_filename()
try:
os.remove(self.get_medium_filename())
os.remove(self.get_small_filename())
except:
pass
super(Photo, self).delete()
Simply put, it deletes the thumbnail files and then calls it’s parent’s delete, which will in turn delete it’s original file.
Aside from creating some optional helper functions like get_small_image_url and/or get_medium_image_url, there’s not much more to be done with the Photo model. What can be done still, however, is in Album. We now have zero or one cover photos for each Album, but it’s going to be tricky to query for this each time, so let’s create a function in Album to help us retrieve the associated cover_photo Photo object:
def get_cover_photo(self):
if self.photo_set.filter(is_cover_photo=True).count() > 0:
return self.photo_set.filter(is_cover_photo=True)[0]
elif self.photo_set.all().count() > 0:
return self.photo_set.all()[0]
else:
return None
That is, if the Album has a photo with is_cover_photo == True, then grab it, otherwise grab the first image. If there are no images in the album, return None. That’s it for the models. Easy, huh? Just run manage.py syncdb, and let Django do the heavy lifting for you.
That’s all for part one of this series on writing a gallery application with Django. Next up: writing the views, urlconfs, and putting it all together. Templating will be left up to you, since there are so many ways to display this information, but some examples will be given to point you in the right direction.
Note to purists: I know that some of the functionality that is being implemented as helper functions in the models would be better implemented as custom template tags, but I find it easier to take a less philosophical stance on the "right" way to do things and sometimes do what’s more practical. In this case, writing model functions is a much easier solution than creating completely new template tags. In either case, moving to a new site will require a rewrite, so I’m not even convinced that it hurts reusability.
分享到:
相关推荐
Key FeaturesA beginners guide to learning python's most popular framework, DjangoBuild fully featured web projects in Django 2.0 through examples.Deploy web applications in quick and reliable fashion ...
资源分类:Python库 所属语言:Python 资源全名:social-auth-app-django-mongoengine-1.0.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
Beginning Django Web App Dev with Python Beginning Django Web App Dev with Python
A calendaring app for Django.
Part I Django’s Core Features Chapter 1 Starting a New Django Project: Building a Startup Categorizer with Blog Chapter 2 Hello World: Building a Basic Webpage in Django Chapter 3 Programming Django ...
Photo Gallery System in Python using Django Free Source Code.zip
python库。 资源全名:social-auth-app-django-1.0.0.tar.gz
python库。 资源全名:social-auth-app-django-1.2.0.tar.gz
python库。 资源全名:django-gallery-widget-1.2.1.dev0.tar.gz
This is a beginners Django course that will take you from absolute scratch to creating a simple Django web app. The course is a hands on course and i strongly advise you to follow along with me so you...
I wanted to write a book about best practices in Django, except Two Scoops is that book, no need to write another one. -- Buddy Lindsey, Host of GoDjango Audrey's illustrations reinforce Audrey and ...
Build a world-class website in less than a week with Django CMS. Beginning Django CMS shows you how to simply and easily write a dynamic website with a full content management system in the backend. ...
附录内容包括命令行基础,安装运行Django,实用Django开发工具,发现、评估、使用Django应用程序,在Google App Engine上使用Django,参与Django项目。 本书适用于Python框架Django初学者,Django Web开发技术人员。
Writing your first Django app
以开发流程来介绍django使用,比起django book 更实用些
Django For Beginners.part4. Django For Beginners.part1-3已上传.
使用Django编写的社交媒体Web App.zip 大学生课程设计 基于django的课程设计 自己大二写的课程设计
Teach Yourself Django in 24 Hours(February 20, 2008).part1.rar
许多成功的网站和APP都基于Django。 Django是一个开源的Web应用框架,由Python写成。 Django Web框架还提供高级功能,例如ORM,数据库迁移,用户身份验证,管理面板和表单。 Django程序员喜欢该框架,因为它具有简化...