世界那么大,我想去看看。Django仿制微信朋友圈九宫格相册(1)

前面文章里的Python和Django知识点很重要,但过于零散。我们学习最终的目的还是应用。我们今天就来看下如何利用Django仿制微信朋友圈的九宫格相册。本教程比较长,会分成2部分发布,欢迎持续关注。我们会分享所有代码,并详细解读。读者需要对Python,Django, HTML, CSS和Javascript有一定的了解,否则读起来会比较吃力。

项目总体思路

对于此项目,我们总体开发思路是这样子的。

用户在后台先创建相册,再上传图片。一个相册可以包含多张图片。

对于单个相册,用户通过后台可以逐一上传单张图片或一次性上传压缩过的ZIP格式的图片包。

用户上传的图片先调整成指定大小和格式再存储,同时生成缩略图存储。

前端两个页面:一个展示相册列表,一个展示相册详情(包含所有图片)。

前端缩略图通过九宫格显示给用户。当用户点击缩略图时,可以查看大图和放大。

用户点击大图可以左右滑动查看上一张和下一张图片(触屏滑动效果)。

图片是responsive的,大小随着浏览器尺寸变化而变化。

项目预期效果

展示相册列表

展示相册详情(微信朋友圈九宫格)

点击缩略图,显示大图,左右滑动。

项目开发所需安装包

除了Django 2.0, 你还需要通过pip安装pillow和django-imagekit两个库。pillow是python的图片库。django-imagekit可以对图片进行尺寸调整,生成缩略图或加水印。因为本项目主要是对图像进行操作,所以安装这两个库是必需的。

下面我们将正式开始本项目的教程。

第一步:创建gallery的应用,并修改配置文件。

利用Django创建一个叫gallery的应用,并把它加到settings.py中INSTALLED_APP里去。同时你应该把imagekit也加到INSTALLED_APP里去。代码如下所示:

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'gallery',

'imagekit',

]

因为我们要使用到静态文件和媒体文件,所以请在settings.py里设置STATIC_ROOT和MEDIA_ROOT.

STATIC_URL ='/static/'

STATIC_ROOT = BASE_DIR +'/static/'

#设置媒体文件夹,对于图片和文件上传很重要

MEDIA_ROOT = os.path.join(BASE_DIR,'media')

MEDIA_URL ='/media/'

最后请把gallery应用的urls也加到项目的urls里去,代码如下所示。

fromdjango.contribimportadmin

fromdjango.urlsimportpath,include

#对于显示静态文件非常重要

fromdjango.confimportsettings

fromdjango.conf.urls.staticimportstatic

urlpatterns = [

path('admin/',admin.site.urls),

path('gallery/',include('gallery.urls')),

] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

第二步:创建模型models.py

我们需要创建两个模型,一个相册Album,一个图片AlbumImage。其中相册与图片之间是单对多的关系(ForeignKey)。我们通过upload_to指定了图片上传目的文件夹(/albums/)和缩略图目的文件夹((/albums/thumb/)。由于我们同时指定了媒体文件根目录MEDIA_ROOT(/media/), 所以最后图片都会上传到/media/albums/文件夹里。

代码如下所示。

#!/usr/bin/env python

# -*- coding: utf-8 -*-

fromdjango.dbimportmodels

fromimagekit.modelsimportProcessedImageField

fromimagekit.processorsimportResizeToFit

fromdjango.urlsimportreverse

classAlbum(models.Model):

title = models.TextField(max_length=1024)

thumb = ProcessedImageField(upload_to='albums',processors=[ResizeToFit(300)],format='JPEG',

options={'quality':90})

is_visible = models.BooleanField(default=True)

create_date = models.DateTimeField(auto_now_add=True)

mod_date = models.DateTimeField(auto_now=True)

slug = models.SlugField(max_length=50,blank=True)

defget_absolute_url(self):

returnreverse('gallery:album_detail',kwargs={'pk':self.pk,'slug':self.slug})

def__str__(self):

returnself.title

classAlbumImage(models.Model):

image = ProcessedImageField(upload_to='albums',processors=[ResizeToFit(1280)],format='JPEG',

options={'quality':70})

thumb = ProcessedImageField(upload_to='albums/thumbs/',processors=[ResizeToFit(300)],format='JPEG',

options={'quality':80},blank=True,null=True)

album = models.ForeignKey('album',on_delete=models.PROTECT)

alt = models.CharField(max_length=255,default='',blank=True)

create_date = models.DateTimeField(auto_now_add=True)

def__str__(self):

returnself.alt

你或许注意到我们使用了imagekit的ProcessedImageField,而不是django自带的ImageField。这里ProcessedImageField与ImageField类似,只不过你可以指定存储图片的大小,格式和质量。你上传的图片会先经由imagekit处理,再进行存储。缩略图thumb默认为空,因为你不需要上传,而直接由上传的image压缩生成。我们在后台会进行处理。

由于数据库里存储的是图片的链接,而不是图片本身。在模板里显示原图和缩略图,我们可以按如下代码操作。注: 一个item是一个AlbumImage对象。

第三步:编写urls.py

在gallery文件下新建urls.py, 加入如下代码。我们只需要两个URLs,一个展示相册列表,一个展示相册详情。

fromdjango.urlsimportpath,re_path

from.importviews

# namespace

app_name ='gallery'

urlpatterns = [

re_path(r'^album/$',views.AlbumListView.as_view(),name='album_list'),

re_path(r'^album/(?P

\d+)/(?P[-\w]+)/$',views.AlbumDetail.as_view(),name='album_detail'),

]

第四步: 编写视图文件views.py

我们使用了Django自带的通用视图DetailView和ListView。如果你不懂什么是通用视图,请阅读

Django视图详解

fromdjango.views.genericimportDetailView,ListView

from.modelsimportAlbum,AlbumImage

classAlbumListView(ListView):

queryset = Album.objects.filter(is_visible=True).order_by("-create_date")

paginate_by =1

classAlbumDetail(DetailView):

model = Album

defget_context_data(self,**kwargs):

# Call the base implementation first to get a context

context =super().get_context_data(**kwargs)

# Add in a QuerySet of all the images

context['images'] = AlbumImage.objects.filter(album=self.object.id)

returncontext

在AlbumDetail里我们通过重写get_context_data向模板里传递了额外的参数images。这样我们在album_detail模板里就不仅能展示相册相关信息,也能展示属于该相册的所有图片了。

未完待续。下一部分我们着重讲解admin处理单个和多个图片上传,以及前端JS和CSS部分。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180606G0XPZ900?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励