diff --git a/.idea/mypy.xml b/.idea/mypy.xml new file mode 100644 index 0000000..46172f7 --- /dev/null +++ b/.idea/mypy.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/akarpov/common/models.py b/akarpov/common/models.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/files/__init__.py b/akarpov/files/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/files/admin.py b/akarpov/files/admin.py new file mode 100644 index 0000000..10c0c6f --- /dev/null +++ b/akarpov/files/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +from akarpov.files.models import BaseFile, Folder + +admin.site.register(BaseFile) +admin.site.register(Folder) diff --git a/akarpov/files/api/__init__.py b/akarpov/files/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/files/apps.py b/akarpov/files/apps.py new file mode 100644 index 0000000..dcdfbd7 --- /dev/null +++ b/akarpov/files/apps.py @@ -0,0 +1,7 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class FilesConfig(AppConfig): + name = "akarpov.files" + verbose_name = _("Files") diff --git a/akarpov/files/migrations/__init__.py b/akarpov/files/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/files/models.py b/akarpov/files/models.py new file mode 100644 index 0000000..79e8d50 --- /dev/null +++ b/akarpov/files/models.py @@ -0,0 +1,43 @@ +from django.db.models import ( + CASCADE, + BooleanField, + CharField, + FileField, + ForeignKey, + SlugField, + TextField, +) +from django_extensions.db.models import TimeStampedModel + +from akarpov.utils.files import user_file_upload_mixin + + +class BaseFile(TimeStampedModel): + """model to store user's files""" + + name = CharField(max_length=100) + description = TextField() + + slug = SlugField(max_length=20, blank=True) + private = BooleanField(default=True) + + user = ForeignKey("users.User", related_name="files", on_delete=CASCADE) + folder = ForeignKey( + "files.Folder", related_name="files", null=True, on_delete=CASCADE + ) + + file = FileField(blank=False, upload_to=user_file_upload_mixin) + + def __str__(self): + return f"file: {self.name}" + + +class Folder(TimeStampedModel): + name = CharField(max_length=100) + slug = SlugField(max_length=20, blank=True) + + user = ForeignKey("users.User", related_name="files", on_delete=CASCADE) + parent = ForeignKey("self", related_name="children", on_delete=CASCADE) + + def __str__(self): + return f"file: {self.name}" diff --git a/akarpov/files/views.py b/akarpov/files/views.py new file mode 100644 index 0000000..e69de29 diff --git a/akarpov/utils/files.py b/akarpov/utils/files.py index c0c0212..f6bde0b 100644 --- a/akarpov/utils/files.py +++ b/akarpov/utils/files.py @@ -68,7 +68,3 @@ def user_file_upload_mixin(instance, filename): username = instance.creator.username return os.path.join(f"uploads/{username}/", filename) - - -def get_filename(filename, request): - return filename.upper() diff --git a/config/settings/base.py b/config/settings/base.py index 85e0b02..2eece31 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -109,6 +109,7 @@ "polymorphic", "cacheops", "extra_settings", + "drf_chunked_upload", # django-cms "cms", "menus", @@ -135,7 +136,13 @@ # "allauth.socialaccount.providers.yandex", ] -LOCAL_APPS = ["akarpov.users", "akarpov.blog", "akarpov.pipeliner", "akarpov.tools.qr"] +LOCAL_APPS = [ + "akarpov.users", + "akarpov.blog", + "akarpov.files", + "akarpov.pipeliner", + "akarpov.tools.qr", +] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = ( DJANGO_APPS + LOCAL_APPS + THIRD_PARTY_APPS + HEALTH_CHECKS + ALL_AUTH_PROVIDERS @@ -494,3 +501,9 @@ "copyright": "admin on akarpov.ru", "user_avatar": "image_cropped", } + + +# DRF_CHUNKED_UPLOAD +# ------------------------------------------------------------------------------ + +DRF_CHUNKED_UPLOAD_PATH = "uploads/chucked/" diff --git a/poetry.lock b/poetry.lock index 8da8ba5..e434c30 100644 --- a/poetry.lock +++ b/poetry.lock @@ -812,6 +812,18 @@ django-timezone-field = ">=5.0" python-crontab = ">=2.3.4" tzdata = "*" +[[package]] +name = "django-chunked-upload" +version = "2.0.0" +description = "Upload large files to Django in multiple chunks, with the ability to resume if the upload is interrupted." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "django-chunked-upload-2.0.0.tar.gz", hash = "sha256:fb8961029d6a9febb974fb24f529c7773c61a9e6467825db861aae29e1f0c978"}, + {file = "django_chunked_upload-2.0.0-py3-none-any.whl", hash = "sha256:f81ce8d7a5df87c75c971b31dd15961712e729f8fbb38a9398c85cc01f89316d"}, +] + [[package]] name = "django-ckeditor" version = "6.5.1" @@ -1301,6 +1313,22 @@ files = [ {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, ] +[[package]] +name = "drf-chunked-upload" +version = "0.5.1" +description = "Upload large files to Django REST Framework in multiple chunks, with the ability to resume if the upload is interrupted." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "drf-chunked-upload-0.5.1.tar.gz", hash = "sha256:7c4faa401295cc24bd270cee41f7f0af5268f91ec477237c4e40bcb51adddfef"}, + {file = "drf_chunked_upload-0.5.1-py3-none-any.whl", hash = "sha256:1a2802d024f21e3ba86158bd31bb8fc33af96c0b8c0b87a759201ca0318f832a"}, +] + +[package.dependencies] +Django = ">=2.2" +djangorestframework = ">=3.11" + [[package]] name = "drf-spectacular" version = "0.25.1" @@ -3650,4 +3678,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "aeb9c87835b2736d82f1d29535a1894b2be0b23471306a919c0594185a0fadc3" +content-hash = "63c03ff6211f20d9ad19aa9761aac2896a70345a441315ea44e09e8e0a370fcc" diff --git a/pyproject.toml b/pyproject.toml index 19f9a86..33c660d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -66,6 +66,8 @@ psycopg2-binary = "^2.9.5" django-cms = "^3.11.1" django-sekizai = "^4.0.0" amzqr = "^0.0.1" +django-chunked-upload = "^2.0.0" +drf-chunked-upload = "^0.5.1" [build-system]