Python django验证并将任何图像转换为jpeg格式,然后保存

Python django验证并将任何图像转换为jpeg格式,然后保存,python,django,django-rest-framework,Python,Django,Django Rest Framework,我在模型中有图像字段类型文件…我想检查用户上传的文件是否为图像,如果其图像我想将其转换为jpeg格式以减小大小和安全性。。我该怎么做 相关观点: class StoreCreateAPIView(generics.CreateAPIView): parser_classes = (MultiPartParser, FormParser) permission_classes = [IsAuthenticated, IsSuperUserOrAdmin] def post

我在模型中有图像字段类型文件…我想检查用户上传的文件是否为图像,如果其图像我想将其转换为jpeg格式以减小大小和安全性。。我该怎么做

相关观点:

class StoreCreateAPIView(generics.CreateAPIView):
    parser_classes = (MultiPartParser, FormParser)
    permission_classes = [IsAuthenticated, IsSuperUserOrAdmin]

    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            file_serial = ProductSerializer(data=request.data, context={"request": request})
            if file_serial.is_valid():
                file_serial.save(author_id=request.user.id)
型号:

def validate_image(image):
    if not image.is_image():
        raise ValidationError('File should be image.')

    file_size = image.file.size
    limit_kb = 200
    if file_size > limit_kb * 1024:
        raise ValidationError("Max size of file is {} KB".format(limit_kb))

# save the uploaded file in user directory
def upload_to_custom_p(instance, filename):
    name = instance.title
    user_id = str(instance.author.id)
    filename = filename.lower()
    return 'Product/img/user_{0}/{1}/{2}'.format(user_id, name, filename)


class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)
    title = models.CharField(max_length=200)
    full_description = models.TextField(null=True, blank=True)
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)
    publish = models.BooleanField(default=False)
    draft = models.BooleanField(default=False)
    slug = models.SlugField(allow_unicode=True, null=True, blank=True)
    image = models.FileField(upload_to=upload_to_custom_p, null=True, blank=True,validators=[validate_image])
自定义路径:

# save the uploaded file in user directory
def upload_to_custom_p(instance, filename):
    name = instance.title
    user_id = str(instance.author.id)
    filename = filename.lower()
    return 'Product/img/user_{0}/{1}/{2}'.format(user_id, name, filename)
‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌‌ ‌

错误日志:

(uenv) [deb@arch academy]$ python3 manage.py runserver
Performing system checks...

/upload/upload/aa.mp4
System check identified no issues (0 silenced).
July 22, 2018 - 15:52:01
Django version 2.0.7, using settings 'academy.settings'
Starting ASGI/Channels version 2.1.1 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
2018-07-22 15:52:01,540 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-07-22 15:52:01,541 - INFO - server - Configuring endpoint tcp:port=8000:interface=127.0.0.1
2018-07-22 15:52:01,543 - INFO - server - Listening on TCP address 127.0.0.1:8000
Internal Server Error: /api/v1/store/view/make/
Traceback (most recent call last):
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py", line 481, in _save
    fh = fp.fileno()
io.UnsupportedOperation: fileno

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 940, in create
    instance = ModelClass.objects.create(**validated_data)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/db/models/query.py", line 417, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/deb/PycharmProjects/ac2/academy/api/v1/store/models.py", line 42, in save
    image.save(image_io, format='JPEG')
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/Image.py", line 1950, in save
    save_handler(self, fp, filename)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 762, in _save
    ImageFile._save(im, fp, [("jpeg", (0, 0)+im.size, 0, rawmode)], bufsize)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py", line 496, in _save
    fp.write(d)
TypeError: string argument expected, got 'bytes'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/views.py", line 483, in dispatch
    response = self.handle_exception(exc)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/views.py", line 443, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/deb/PycharmProjects/ac2/academy/api/v1/store/views.py", line 269, in post
    file_serial.save(author_id=request.user.id)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 214, in save
    self.instance = self.create(validated_data)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 957, in create
    raise TypeError(msg)
TypeError: Got a `TypeError` when calling `Product.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Product.objects.create()`. You may need to make the field read-only, or override the ProductSerializer.create() method to handle this correctly.
Original exception was:
 Traceback (most recent call last):
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py", line 481, in _save
    fh = fp.fileno()
io.UnsupportedOperation: fileno

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 940, in create
    instance = ModelClass.objects.create(**validated_data)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/django/db/models/query.py", line 417, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/deb/PycharmProjects/ac2/academy/api/v1/store/models.py", line 42, in save
    image.save(image_io, format='JPEG')
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/Image.py", line 1950, in save
    save_handler(self, fp, filename)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 762, in _save
    ImageFile._save(im, fp, [("jpeg", (0, 0)+im.size, 0, rawmode)], bufsize)
  File "/home/deb/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py", line 496, in _save
    fp.write(d)
TypeError: string argument expected, got 'bytes'

[2018/07/22 15:52:32] HTTP POST /api/v1/store/view/make/ 500 [0.42, 127.0.0.1:52918]
如果您只想上传一个文件,建议使用ImageField 图像,它会自动验证上载的对象是否为有效图像

覆盖产品模型的保存方法,并使用PIL包的Image类将其转换为JPEG

如果您只想上传一个文件,建议使用ImageField 图像,它会自动验证上载的对象是否为有效图像

覆盖产品模型的保存方法,并使用PIL包的Image类将其转换为JPEG


如果只想上载图像,则必须使用ImageField,它会自动验证上载的对象是否为有效图像。thnaks如何在保存前转换图像?我想在保存之前将任何格式的图像转换为jpeg?检查我的答案,让我知道任何问题,我还没有测试代码。我应该在哪里使用def save?在产品模型内部如果您只想上载图像,必须使用ImageField,它会自动验证上载的对象是否为有效图像。thnaks如何在保存之前转换图像?我想在保存之前将任何格式的图像转换为jpeg格式?检查我的答案,让我知道任何问题,我还没有测试代码。我应该在哪里使用def save?在产品模型内部它会给我一个错误,说:TypeError at/api/v1/store/view/make/调用Product.objects.create时发生TypeError。这可能是因为序列化程序类上的可写字段不是Product.objects.create的有效参数。您可能需要将字段设置为只读,或重写ProductSerializer.create方法以正确处理此问题。最初的例外是:回溯最近的调用最后一次:File/home/mohammadreza/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py,第477行,在_save中如果我使用只读“image”,它将修复bud image将不会保存更新您正在创建产品的代码,引起此错误的代码是哪一行?此文件是\u serial.saveauthor\u id=request.user.id行引起错误请确认我猜此问题与save方法中的代码无关。它给我的错误是:TypeError at/api/v1/store/view/make/get在调用Product.objects.create时出现了TypeError。这可能是因为序列化程序类上的可写字段不是Product.objects.create的有效参数。您可能需要将字段设置为只读,或重写ProductSerializer.create方法以正确处理此问题。最初的例外是:回溯最近的调用最后一次:File/home/mohammadreza/PycharmProjects/ac2/uenv/lib/python3.6/site-packages/PIL/ImageFile.py,第477行,在_save中如果我使用只读“image”,它将修复bud image将不会保存更新您正在创建产品的代码,引发此错误的代码行是此文件\u serial.saveauthor\u id=request.user.id行引发错误请确认我猜此问题与save方法中的代码无关
from django.core.files.base import ContentFile
from PIL import Image
from io import BytesIO


class Product(models.Model):
   # attribute lies here
   ...

   def save(self, *args, **kwargs):
      if self.image:
         filename = "%s.jpg" % self.image.name.split('.')[0]

         image = Image.open(self.image)
         # for PNG images discarding the alpha channel and fill it with some color
         if image.mode in ('RGBA', 'LA'):
            background = Image.new(image.mode[:-1], image.size, '#fff')
            background.paste(image, image.split()[-1])
            image = background
         image_io = BytesIO()
         image.save(image_io, format='JPEG', quality=100)

         # change the image field value to be the newly modified image value
         self.image.save(filename, ContentFile(image_io.getvalue()), save=False)

      super(Product, self).save(*args, **kwargs)