lehins / django-smartfields

Django Model Fields that are smart.
MIT License
98 stars 13 forks source link

Can't clear image from post object #17

Open ghost opened 5 years ago

ghost commented 5 years ago

Hello,

if i try to use the ImageProcessor like so:

postcover = fields.ImageField(
                              verbose_name="Post Cover",
                              blank=True,
                              null=True,
                              upload_to=get_file_path_user_uploads,
                              validators=[default_image_size, default_image_file_extension],
                              dependencies=[FileDependency(processor=ImageProcessor(
                                  format='PNG', quality=99, scale={'max_width': 700, 'max_height': 700}))])

and i create a new post object with a Postcover everything first seems to work fine until i try to delete the image i uploaded previously again. It seems that the ImageProcessor always expects a file while saving the form if one has been set before. Anyways here is my full trace:

Traceback (most recent call last):
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/user123/docs/PyCharm/app/app_Accounts/decorators.py", line 33, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/ratelimit/decorators.py", line 30, in _wrapped
    return fn(*args, **kw)
  File "/home/user123/docs/PyCharm/app/app/views.py", line 473, in post_edit
    post.save()
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/models.py", line 28, in save
    super(SmartfieldsModelMixin, self).save(*args, **kwargs)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/base.py", line 718, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/base.py", line 748, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/base.py", line 809, in _save_table
    for f in non_pks]
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/base.py", line 809, in <listcomp>
    for f in non_pks]
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/fields/__init__.py", line 79, in pre_save
    self.manager.process(model_instance)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/managers.py", line 154, in process
    self._process(d, instance)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/managers.py", line 130, in _process
    dependency.process(instance, value, progress_setter=progress_setter)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/dependencies.py", line 206, in process
    **self._processor_params
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/processors/base.py", line 23, in __call__
    stashed_value=stashed_value, **self.get_params(**kwargs))
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/smartfields/processors/image.py", line 287, in process
    cur_pos = value.tell()
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/core/files/utils.py", line 21, in <lambda>
    tell = property(lambda self: self.file.tell)
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/fields/files.py", line 41, in _get_file
    self._require_file()
  File "/home/user123/docs/PyCharm/app/venv/lib/python3.6/site-packages/django/db/models/fields/files.py", line 38, in _require_file
    raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
ValueError: The 'postcover' attribute has no file associated with it. 

my expected behaviour here is that i can always clear the postcover, which is not possible at the moment.

lehins commented 5 years ago

@venomone Sorry you are having trouble with it. It seems like a bug and I am not quite sure what's the actual cause, it is likely that something has changed in django that wasn't happening before. I haven't used this package in a few years, in fact I haven't touched django or python in over three years. I am way too busy writing Haskell :) That being said, I don't think it should be terribly hard too fix, so if you'll find a solution for this, I'll be happy to accept a PR.

This is a cool package, and I'd like to find some time to take care of all outstanding issues, so people can continue using it, but I am not sure how soon I'll be able to get to it.

ghost commented 5 years ago

The Problem for me is that i'm new to Django and actually dont have that much exp on me but maybe i will find it or smb. else, Anyways thx for the label.

ghost commented 5 years ago

As a quick workaround i try to imitate what's going-on behind your imageprocessor, have a look at this for first aid:

modely.py

Class Post
...
postcover = fields.ImageField(
        verbose_name="Post Cover",
        blank=True,
        null=True,
....
    def save(self, *args, **kwargs):
        super(Post, self).save(*args, **kwargs)
        if self.postcover:
            if os.path.exists(self.postcover.path):
                imageTemproary = Image.open(self.postcover)
                outputIoStream = BytesIO()
                imageTemproaryResized = imageTemproary.resize((500, 375))
                imageTemproaryResized.save(outputIoStream, format='PNG')
                outputIoStream.seek(0)
                self.postcover = InMemoryUploadedFile(outputIoStream, 'ImageField',
                                                  "%s.png" % self.postcover.name.split('.')[0], 'image/png',
                                                  sys.getsizeof(outputIoStream), None)
        super(Post, self).save(*args, **kwargs)