「阿里OSS」集成Django的基本配置及使用-2

前言:

之前曾经写过的「阿里OSS」集成Django的基本配置及使用,里边在使用OSS是通过Django的两个信号量(signals)去实现的,一个post_init获取保存动作前的图片,一个post_save获取保存动作后的图片.通过对比两张图片,如果发生变化的话则将图片进行上传。

实现的思路没什么问题,在后期的使用过程中主要有如下两个问题发生:

  1. post_init信号会在除了保存动作以外的情况发生,这样一直对post_init进行监听,对整个代码执行的效率有影响;
  2. 如果项目中大量的ImageField都需要用到OSS的话,这样的信号量复用起来太糟糕。

解决思路:

  1. 通过自定义一个ImageField,从而更灵活去对OSS进行配置;
  2. 找到ImageField对象在进行save动作的方法,在其后上传图片即可。

实现:

  1. 自定义一个ImageField类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import oss2

    from django.db.models import ImageField
    from django.conf import settings


    class OssImageField(ImageField):

    def pre_save(self, model_instance, add):
    file = getattr(model_instance, self.attname)
    if file and not file._committed: # 这行代码判断文件是否有改动
    file.save(file.name, file.file, save=False)

    # 以下代码块为自定义部分:上传到oss
    auth = oss2.Auth(settings.ACCESS_KEY_ID, settings.ACCESS_KEY_SECRET)
    bucket = oss2.Bucket(auth, settings.ALI_OSS_ENDPOINT, settings.ALI_BUCKET_NAME)
    bucket.put_object_from_file('media/' + file.name, file.path)

    return file
  2. 使用:

    由于OssImageField继承的是django的model中的ImageField类,所以使用的时候就跟跟普通的Field一样使用,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    ...

    class Designer(models.Model):
    name = models.CharField(max_length=50, verbose_name="设计师名称")
    country = models.CharField(max_length=50, verbose_name="国籍")
    portrait = OssImageField(upload_to='designer/portrait/%Y/%m', verbose_name="肖像", help_text='尺寸500*500为宜')
    bg_image = OssImageField(upload_to='designer/bg_image/%Y/%m', verbose_name="背景图片", help_text='尺寸1000*1000为宜')
    desc = models.TextField(verbose_name='设计师描述')

    class Meta:
    verbose_name = '设计师'
    verbose_name_plural = verbose_name

    def __str__(self):
    return self.name

    ...
  3. 关于OSS的基本配置请看上一篇文章


参考: