一、系统环境
- deepin 15.10.2 桌面版 64位
- PyCharm Professional 2019.1.2
- Django 2.2.4
- Python 3.7.4
二、基本概念
class ImageField(upload_to = None, height_field = None, width_field = None, max_length = 100, **options)[source]
ImageField 是用于保存图像文件的字段。其基本用法和特性与 FileField 一样,只不过多了两个属性 height_field 和 width_field,分别保存图片的高度和宽度信息。默认情况下,该字段在 HTML 中表现为一个 ClearableFileInput 标签。在数据库内,我们实际保存的是一个字符串类型,默认最大长度 100,可以通过 max_length 参数自定义。真实的图片是保存在服务器的文件系统内的。
三、使用步骤
- 配置 settings.py
# settings.py
# 配置 MEDIA_ROOT 作为你上传文件在服务器中的基本路径
MEDIA_ROOT = os.path.join(BASE_DIR, 'upload') # 注意此处不要写成列表或元组的形式
# 配置 MEDIA_URL 作为公用 URL,指向上传文件的基本路径
MEDIA_URL = '/media/'
# 这里特意写成 upload 和 media,而不是统一写成 media 或 upload,是为了便于理解 MEDIA_ROOT 和 MEDIA_URL 的作用和区别
- models.py 中设置 ImageField 字段
# models.py
def user_directory_path(instance, filename):
ext = filename.split('.').pop()
filename = '{0}{1}.{2}'.format(instance.name, instance.identity_card, ext)
return os.path.join(instance.major.name, filename) # 系统路径分隔符差异,增强代码重用性
class Student(models.Model):
major = models.ForeignKey(Major, on_delete = models.CASCADE)
name = models.CharField('姓名', max_length = 10)
identity_card = models.CharField('身份证号', max_length = 20, unique = True)
......
# upload_to 参数接收一个回调函数 user_directory_path,该函数返回具体的路径字符串,图片会自动上传到指定路径下,即 MEDIA_ROOT + upload_to
# user_directory_path 函数必须接收 instace 和 filename 两个参数。参数 instace 代表一个定义了 ImageField 的模型的实例,说白了就是当前数据记录;filename 是原本的文件名
# null 是针对数据库而言,如果 null = True, 表示数据库的该字段可以为空;blank 是针对表单的,如果 blank = True,表示你的表单填写该字段的时候可以不填,但是对数据库来说,没有任何影响
photo = models.ImageField('照片', upload_to = user_directory_path, blank = True, null = True)
......
# 这里定义一个方法,作用是当用户注册时没有上传照片,模板中调用 [ModelName].[ImageFieldName].url 时赋予一个默认路径
def photo_url(self):
if self.photo and hasattr(self.photo, 'url'):
return self.photo.url
else:
return '/media/default/user.jpg'
- 配置 urls.py
# 注意是项目根路由 urls.py 文件,而不是应用中的二级路由 urls.py 文件
# 方法一:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
......
] + static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
# 方法二:
from django.urls import re_path
from django.conf import settings
from django.views.static import serve
urlpatterns = [
......
# 注意是 media 而不是 upload
re_path(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]
- 配置 views.py
# views.py
from django.shortcuts import get_object_or_404
from .models import Major
def add_student(request):
if request.method == 'POST':
major = get_object_or_404(Major, pk = request.POST['major'])
major.student_set.create(
......
photo = request.FILES.get('photo'),
)
......
......
- 模板中呈现图片
<!-- 调用的是 Student 模型中的 photo_url 方法,而不是直接调用 Student.photo.url。如果用户在注册时没有上传照片,后者会报错 -->
<img id="photo" src="{{ student.photo_url }}">
四、django-imagekit 的使用
imagekit 可以实现对上传图片的大小、质量、格式、水印、去边框等进行定制,功能很强大。
- 准备工作
pip install pillow
pip install django-imagekit
# settings.py
INSTALLED_APPS = [
'myapp',
'imagekit', # 注册 imagekit
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
- 配置 models.py
# models.py
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
......
class Student(models.Model):
......
photo = models.ImageField('照片', upload_to = user_directory_path, blank = True, null = True)
photo_295_413 = ImageSpecField( # 注意:ImageSpecField 不会生成数据库表的字段
source = 'photo',
processors = [ResizeToFill(295, 413)], # 处理成一寸照片的大小
format = 'JPEG', # 处理后的图片格式
options = {'quality': 95} # 处理后的图片质量
)
......
def photo_295_413_url(self):
if self.photo_295_413 and hasattr(self.photo_295_413, 'url'):
return self.photo_295_413.url
else:
return '/media/default/user.jpg'
# 默认情况下,imagekit 使用 imagekit.cachefiles.namers.source_name_as_path 来生成图片的路径
# 上例定制后的图片会上传到 [MEDIA_ROOT]/CACHE/images/[upload_to]/[md5处理后的名字.jpg]
# 想要自定义路径请参考 https://blog.csdn.net/weixin_42368421/article/details/84955946
- 模板中呈现图片
<img id="photo" src="{{ student.photo_295_413_url }}">
网友评论