chibisov / django-proxy-storage

Provides simple Django storage that proxies every operation to original storage and saves meta information about files to database
http://chibisov.github.io/django-proxy-storage/docs
40 stars 11 forks source link

Django 2.0.3 #10

Open dizjis opened 6 years ago

dizjis commented 6 years ago

Здравствуйте.

Попытался использовать в связке с вышеозначенной версией django. Использовал ORMMetaBackend, основываясь на примере Authorization

# storages.py
from django.core.files.storage import FileSystemStorage
from proxy_storage.storages.base import ProxyStorageBase
from proxy_storage.meta_backends.orm import ORMMetaBackend
from proxy_storage.meta_backends.orm import ProxyStorageModelBase, ContentObjectFieldMixin
from django.utils.deconstruct import deconstructible

class ProxyStorageModel(ContentObjectFieldMixin, ProxyStorageModelBase):
    pass

orm_meta_backend = ORMMetaBackend(model=ProxyStorageModel)

@deconstructible
class FileSystemProxyStorage(ProxyStorageBase):
    meta_backend = orm_meta_backend
    original_storage = FileSystemStorage(location='/files/download/')

Мне пришлось добавить декоратор @deconstructible иначе проект вообще не запускался (в примере Authorization этого декоратора нет) Поле в модели:

letter = ProxyStorageFileField(
        _('Основание'),
        validators=[
            FileExtensionValidator(allowed_extensions=['pdf']),
            FileMimeTypeValidator(allowed_mime_types=['application/pdf']),
        ],
        blank=True,
        storage=FileSystemProxyStorage(),
    )

При сохранении модели вылазит ошибка следующего содержания:

Traceback (most recent call last): File "\venv\lib\site-packages\django\core\handlers\exception.py", line 35, in inner response = get_response(request) File "\venv\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response response = self.process_exception_by_middleware(e, request) File "\venv\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/mso\mso_users\views.py", line 26, in registration mso_user.save() File "\venv\lib\site-packages\django\contrib\auth\base_user.py", line 73, in save super().save(*args, **kwargs) File "\venv\lib\site-packages\django\db\models\base.py", line 729, in save force_update=force_update, update_fields=update_fields) File "\venv\lib\site-packages\django\db\models\base.py", line 759, in save_base updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) File "\venv\lib\site-packages\django\db\models\base.py", line 842, in _save_table result = self._do_insert(cls._base_manager, using, fields, update_pk, raw) File "\venv\lib\site-packages\django\db\models\base.py", line 880, in _do_insert using=using, raw=raw) File "\venv\lib\site-packages\django\db\models\manager.py", line 82, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "\venv\lib\site-packages\django\db\models\query.py", line 1125, in _insert return query.get_compiler(using=using).execute_sql(return_id) File "\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1282, in execute_sql for sql, params in self.as_sql(): File "\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1235, in as_sql for obj in self.query.objs File "\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1235, in for obj in self.query.objs File "\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1234, in <listcomp> [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields] File "\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1184, in pre_save_val return field.pre_save(obj, add=True) File "\venv\lib\site-packages\django\db\models\fields\files.py", line 287, in pre_save file.save(file.name, file.file, save=False) File "\venv\lib\site-packages\django\db\models\fields\files.py", line 87, in save self.name = self.storage.save(name, content, max_length=self.field.max_length) TypeError: save() got an unexpected keyword argument 'max_length'

chibisov commented 6 years ago

Привет. К сожалению у меня сейчас нет времени разбираться с ошибкой. Будет круто, если вы найдете проблему и пришлете пул реквест =)

dizjis commented 6 years ago

Где ошибка то я нашел, и даже вроде починил костылем. Проблема в том, что метод save класса Storage объявлен как def save(self, name, content, max_length=None), а в django-proxy-storage он переопределен в def save(self, name, content, original_storage_path=None): В итоге, джанговский класс FieldFile(File) в своем методе save дергает self.storage.save(name, content, max_length=self.field.max_length), где вызывает метод класса из django-proxy-storage, который ничего про max_length не знает. Локально я починил, добавив метод save с объявлением нужных параметров:

@deconstructible
class FileSystemProxyStorage(ProxyStorageBase):
    meta_backend = meta_backend
    original_storage = FileSystemStorage(location=PROXY_STORAGE_DIR)

    def save(self, name, content, original_storage_path=None, max_length=None):
        return super().save(name, content, original_storage_path)

Но я понятия не имею, насколько это корректно и не сломается ли что-нибудь в дальнейшем из-за отсутствия max_length