Loading

django 处理图片上传

必要的设置

图片属于一种媒体文件,它与静态文件类似,需要设置一个统一的目录,便于集中存储和访问。

settings
这类需要框架统一设置的参数,当然应该在settings.py中。在底部加上:

# 媒体文件地址
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

MEDIA_ROOT和MEDIA_URL是用户上传文件保存、访问的位置:

  • 在前面的Profile中我们设置了upload_to参数。有了这个参数,文件上传后将自动保存到项目根目录的media文件夹中。 os.path.join(MEDIA_ROOT, 'media/')指定了media文件夹的位置。
  • MEDIA_URL代表用户通过URL来访问这个本地地址的URL。设置好这个参数后,用户就可以通过解析url,很方便的获取文件的地址。这样做的好处是避免的硬编码,让代码更容易维护。

urls设置

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    ...
]

#添加这行
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

models字段

使用ImageField,所依赖模块
使用模型处理上传文件:将属性定义成models.ImageField类型
如果属性类型为imageField需要安装Pilow
pip install Pillow

定义模型

from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
    # 与 User 模型构成一对一的关系
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    # 电话号码字段
    phone = models.CharField(max_length=20, blank=True)
    # 头像
    avatar = models.ImageField(upload_to='avatar/%Y%m%d/', blank=True)
    # 个人简介
    bio = models.TextField(max_length=500, blank=True)

    def __str__(self):
        return 'user {}'.format(self.user.username)

upload_to指定了图片上传的位置,即/media/avatar/%Y%m%d/。%Y%m%d是日期格式化的写法,会最终格式化为系统时间。比如说图片上传是2018年12月5日,则图片会保存在/media/avatar/2018205/中。
注意ImageField字段不会存储图片本身,而仅仅保存图片的地址。

forms

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('phone', 'avatar', 'bio')

views


def profile_edit(request, id):
    ...

    # 修改本行
    # 上传的文件保存在 request.FILES 中,通过参数传递给表单类
    profile_form = ProfileForm(request.POST, request.FILES)

    if profile_form.is_valid():
        ...

        # 如果 request.FILES 存在文件,则保存
        if 'avatar' in request.FILES:
            profile.avatar = profile_cd["avatar"]

        ...

  • 表单上传的文件对象存储在类字典对象request.FILES中,因此需要修改表单类的参数,将它一并传递进去。
  • 如果request.FILES中存在键为avatar的元素,则将其赋值给profile.avatar(注意保存的是图片地址);否则不进行处理。

html

<form ... enctype="multipart/form-data">{% csrf_token %}
    <!-- avatar -->
    <div class="form-group">
        <label for="avatar">上传头像</label>
        <input type="file" class="form-control-file" name="avatar" id="avatar">
    </div>
</form>

<img src="{{ profile.avatar.url }}" style="max-width: 20%; border-radius: 15%;" class="col-md-4">
  • img里profile.avatar.url中profile是在view视图里返回的用户信息的实例

图片处理思考的点

除了上传,图片的处理还包括验证格式、改变尺寸、更名、裁剪、美化等多种多样的需求。
如果上传的图片重名,会导致报错吗?请试试看。    # 这个如果上传重名图片,会在名字后形成一段乱码,然后可以重复上传相同图片
更改图片仅仅会改变字段中存储的url,并不会真正删除图片本身。因此在处理大容量文件时要小心,需要额外的方法进行清理。
posted @ 2021-07-19 17:38  封灵寒武  阅读(178)  评论(0编辑  收藏  举报