目录:Django 2.1 从零开始搭建博客网站系列
服务器环境搭建(选学)
- 在阿里云服务器从零开始上线Django项目:Ubuntu18.04+Python3+Django2,并通过公网IP访问
小试牛刀——简单的博客网站
- 一、Django2.1 搭建简单的博客网站
- 二、Django2.1 搭建简单的博客网站扩展——自定义模板和静态文件位置
庖丁解牛——多用户的博客网站之用户模块
- 三、Django2.1 搭建多用户的博客网站——登录
- 四、Django2.1 搭建多用户的博客网站——注册
- 五、Django2.1 搭建多用户的博客网站——修改密码
- 六、Django2.1 搭建多用户的博客网站——重置密码
- 七、Django2.1 搭建多用户的博客网站——维护个人详细信息
- 八、Django2.1 搭建多用户的博客网站——头像上传
- 九、Django2.1 搭建多用户的博客网站——用户模块小结
庖丁解牛——多用户的博客网站之文章模块
- 十、Django2.1 搭建多用户的博客网站——文章栏目
- 十一、Django2.1 搭建多用户的博客网站——简单的文章发布
- 十二、Django2.1 搭建多用户的博客网站——使用Markdown发布文章
- 十三、Django2.1 搭建多用户的博客网站——修改和删除文章
- 十四、Django2.1 搭建多用户的博客网站——向用户展示文章
- 十五、Django2.1 搭建多用户的博客网站——文章模块小结
华丽转身——多用户的博客网站之扩展功能
- 十六、Django2.1 搭建多用户的博客网站——文章点赞功能
- 十七、Django2.1 搭建多用户的博客网站——统计文章浏览次数
- 十八、Django2.1 搭建多用户的博客网站——文章评论功能
- 十九、Django2.1 搭建多用户的博客网站——使用自定义模板标签
- 二十、Django2.1 搭建多用户的博客网站——文章标签
- 二十一、Django2.1 搭建多用户的博客网站——美图模块
- 未完待续
正文:
本模块的功能是用户提交图片的网址,然后由程序将图片下载并保存到指定的位置,最后用户可以在“美图”模块里浏览这些图片。
1、创建应用
python manage.py startapp image
在 ./lehhe/settings.py 的 INSTALLED_APPS 中新增 image
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'account',
'article',
'image', #新增
]
如果没安装python的Pillow模块,需要先安装。安装命令是
pip install pillow
2、增加图片
2.1 数据模型类
编辑 ./image/models.py
from django.db import models
from django.contrib.auth.models import User
from slugify import slugify
class Image(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="images")
title = models.CharField(max_length=300)
url = models.URLField()
slug = models.SlugField(max_length=500, blank=True)
description = models.TextField(blank=True)
created = models.DateField(auto_now_add=True, db_index=True)
image = models.ImageField(upload_to='images/%Y/%m/%d')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Image, self).save(*args, **kwargs)
执行以下命令更新数据库
python manage.py make migrations
python manage.py migrate
2.2 表单类
编辑 ./image/forms.py
from django import forms
from django.core.files.base import ContentFile
from slugify import slugify
from urllib import request
from .models import Image
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ('title', 'url', 'description')
def clean_url(self):
url = self.cleaned_data['url']
valid_extensions = ['jpg', 'jpeg', 'png']
extension = url.rsplit('.', 1)[1].lower()
if extension not in valid_extensions:
raise forms.ValidationError("The given Url does not match valid image extension.")
return url
def save(self, force_insert=False, force_update=False, commit=True):
image = super(ImageForm, self).save(commit=False)
image_url = self.cleaned_data['url']
image_name = '{0}.{1}'.format(slugify(image.title), image_url.rsplit('.', 1)[1].lower())
response = request.urlopen(image_url)
image.image.save(image_name, ContentFile(response.read()), save=False)
if commit:
image.save()
return image
2.3 视图函数
编辑 ./image/views.py
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from .forms import ImageForm
from .models import Image
@login_required(login_url='/account/login/')
@csrf_exempt
@require_POST
def upload_image(request):
form = ImageForm(data=request.POST)
if form.is_valid():
try:
new_item = form.save(commit=False)
new_item.user = request.user
new_item.save()
return JsonResponse({'status': "1"})
except:
return JsonResponse({'status': "0"})
@login_required(login_url='/account/login/')
def list_images(request):
images = Image.objects.filter(user=request.user)
return render(request, 'image/list_images.html', {"images": images})
2.4 设置路由
编辑 ./lehehe/urls.py
path('image/', include('image.urls')),
创建 ./image/urls.py
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
app_name = 'image' # 一定要写这一行,否则html中会报错 'image' is not a registered namespace
urlpatterns = [
path('list-images/', views.list_images, name="list_images"),
path('upload-image/', views.upload_image, name='upload_image'),
]
2.5 模板文件
编辑 ./templates/article/header.html 在“文章管理”之后添加
图片管理
编辑 ./templates/article/leftslider.html 增加“图片管理”栏目
图片管理
创建 ./templates/image/list_images.html
{% extends "article/base.html" %}
{% load staticfiles %}
{% block title %}images{% endblock %}
{% block content %}
{% endblock %}
2.6 测试
访问 http://127.0.0.1:8000/image/list-images/
增加了两张图片后,页面如下
查看项目目录,观察images文件夹,如图
查看数据库中的 image_image 表
3、删除图片
3.1 视图函数
编辑 ./image/views.py 新增 del_image 方法
@login_required(login_url='/account/lobin/')
@require_POST
@csrf_exempt
def del_image(request):
image_id = request.POST['image_id']
try:
image = Image.objects.get(id=image_id)
image.delete()
return JsonResponse({'status':"1"})
except:
return JsonResponse({'status':"2"})
3.2 设置路由
编辑 ./image/urls.py 新增路由
path('del-image/', views.del_image, name='del_image'),
3.3 模板文件
在 ./templates/image/list_images.html 中新增如下js代码
function del_image(the, image_id){
var image_title = $(the).parents("tr").children("td").eq(1).text();
layer.open({
type: 1,
skin: "layui-layer-rim",
area: ["400px", "200px"],
title: "删除图片",
content: '是否确定删除《'+image_title+'》
',
btn:['确定', '取消'],
yes: function(){
$.ajax({
url: '{% url "image:del_image" %}',
type:"POST",
data: {"image_id":image_id},
success: function(e){
var status = e['status']
if(status=="1"){
parent.location.reload();
layer.msg("has been deleted.");
}else{
layer.msg("删除失败");
}
},
})
},
});
}
访问 http://127.0.0.1:8000/image/list-images/ 点击页面中的删除图标,效果如图
点击确定后,图片将从列表和数据表中删除,却没有从images文件夹中删除,如想进一步删除,还需要继续优化。
3.4 完善图片列表
图片列表现在只显示了图片地址,下面我们将在图片地址的位置显示为图片。
在 ./lehehe/settings.py 中增加如下配置
# 图片保存地址配置
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
修改 ./lehehe/urls.py 引入settings和static
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
在 ./templates/image/list_images.html 中修改这行代码
{{ image.image }}
为
访问 http://127.0.0.1:8000/image/list-images 发现原来提交的图片无法显示了,因为我图片的访问地址发生了变化,所以需要重新提交,重新提交之后,页面如下
3.5 使用缩略图应用
上面我们虽然现实了图片,但是仅仅是对原图尺寸做了修改,读取的仍然是原图。下面我们就用缩略图来代替。幸运地是我们不用从零开始写缩略图功能了,使用缩略图应用 sorl-thumbnail 即可,其官网地址是 https://sorl-thumbnail.readthedocs.io
首先安装这个应用
pip install sorl-thumbnail
然后把这个应用配置在 ./lehehe/settings.py 的 INSTALLED_APPS 中
'sorl.thumbnail',
接着更新数据库
python manage.py make migrations thumbnail
python manage.py migrate
最后在 ./templates/image/list_images.html 中引入sort-thumbnail,修改之前的显示图片代码
{% load thumbnail %}
......
{% thumbnail image.image "100x100" crop="center" as im %}
{% endthumbnail %}
重新访问 http://127.0.0.1:8000/image/list-images 此时的图片已经是原图的缩略图了。
4、展示图片
“瀑布流”是目前很流行的布局模式,下面我们将使用“瀑布流”的布局来展示图片。
4.1 使用瀑布流插件
插件地址 http://github.com/jmlp-131092/mp-mansory.js ,下载这个插件后,把其中的 mp.mansory.min.js 文件复制到 ./static/js 目录中,然后在 ./static/css 目录中创建 mansory-style.css 文件,并输入以下代码:
#my-gallery-container {
background-color: #ededed;
}
.falls_item {
border: #c6c6c6 2px solid;
width: 100%;
background-color: white;
min-height: 100px;
padding: 5px;
margin: 10px 0px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 2px 2px;
border-radius: 4px;,
}
.falls_item:hover {
opacity: 0.5;
}
.falls_item.h150{
width: 100%;
min-height: 150px;
}
.falls_item.h200{
width: 100%;
min-height: 200px;
}
.falls_item.h250{
width: 100%;
min-height: 200px;
}
.falls_padding{
padding: 10px 5px;
}
.falls_item img {
max-width: 100%;
}
之所以不使用 style.css 文件,是因为原文件中的样式表名称跟本项目中已经使用的 bootstrap.css 有重复,如果使用就会覆盖原有名称,因此这里重写并重新命名。
4.2 视图函数
编辑 ./image/views.py 新增 falls_images 方法
def falls_images(request):
images = Image.objects.all()
return render(request, 'image/falls_images.html', {"images": images})
4.3 设置路由
编辑 ./image/urls.py
path('images/', views.falls_images, name="falls_images"),
4.4 模板文件
编辑 ./templates/header.html 中的导航代码,增加“美图”栏目
美图
创建 ./templates/image/falls_images.html
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}Images{% endblock %}
{% block content %}
{% for image in images %}
{{ image.title }}
{% endfor %}
{% endblock %}
访问 http://127.0.0.1:8000/image/images/ 页面如图
4.5 查看图片的详细信息
上面只是展示了所有图片,下面我们实现点击某张图片显示图片详细信息,并能查看原图。一种方式是使用类似查看文章详细内容的方法,另一种方式是借助layer插件使用纯粹前端的方式。第一种方式参考之前的文章即可,下面我们将采用第二种方式来实现。
修改 ./templates/image/falls_images.html
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}Images{% endblock %}
{% block content %}
{% endblock %}
4.6 测试
访问 http://127.0.0.1:8000/image/images/ 点击一张图片,效果如图