{"id":13671512,"url":"https://github.com/joegasewicz/flask-file-upload","last_synced_at":"2025-04-07T11:11:00.203Z","repository":{"id":36565755,"uuid":"227824369","full_name":"joegasewicz/flask-file-upload","owner":"joegasewicz","description":"Easy file uploads for Flask.","archived":false,"fork":false,"pushed_at":"2023-02-16T04:15:10.000Z","size":14330,"stargazers_count":154,"open_issues_count":18,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-31T08:12:21.166Z","etag":null,"topics":["flask","flask-sqlalchemy","sqlalchemy","upload-images","upload-videos"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joegasewicz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-12-13T11:26:42.000Z","updated_at":"2024-09-17T23:09:43.000Z","dependencies_parsed_at":"2024-01-03T01:20:33.708Z","dependency_job_id":"e9f6bf2e-f1be-4f1a-a95e-71dc74b6bdf6","html_url":"https://github.com/joegasewicz/flask-file-upload","commit_stats":{"total_commits":324,"total_committers":7,"mean_commits":"46.285714285714285","dds":"0.14814814814814814","last_synced_commit":"d914b3ab22d9466d7fdffff7941becf9fbb181ee"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-file-upload","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-file-upload/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-file-upload/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joegasewicz%2Fflask-file-upload/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joegasewicz","download_url":"https://codeload.github.com/joegasewicz/flask-file-upload/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640465,"owners_count":20971557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flask","flask-sqlalchemy","sqlalchemy","upload-images","upload-videos"],"created_at":"2024-08-02T09:01:11.546Z","updated_at":"2025-04-07T11:11:00.181Z","avatar_url":"https://github.com/joegasewicz.png","language":"Python","funding_links":[],"categories":["Python","Third-Party Extensions"],"sub_categories":["Utils"],"readme":"[![Upload Python Package](https://github.com/joegasewicz/flask-file-upload/actions/workflows/python-publish.yml/badge.svg)](https://github.com/joegasewicz/flask-file-upload/actions/workflows/python-publish.yml)\n[![Python application](https://github.com/joegasewicz/flask-file-upload/actions/workflows/python-app.yml/badge.svg)](https://github.com/joegasewicz/flask-file-upload/actions/workflows/python-app.yml)\n[![Documentation Status](https://readthedocs.org/projects/flask-file-upload/badge/?version=latest)](https://flask-file-upload.readthedocs.io/en/latest/?badge=latest)\n[![PyPI version](https://badge.fury.io/py/flask-file-upload.svg)](https://badge.fury.io/py/flask-file-upload)\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/flask-file-upload)\n![FlaskFileUpload](assets/logo.png?raw=true \"Title\")\n\nLibrary that works with Flask (version 1 or 2) and SqlAlchemy to store\nfiles on your server \u0026 in your database\n\nRead the docs: [Documentation](https://flask-file-upload.readthedocs.io/en/latest/)\n\n## Installation\nPlease install the latest release:\n```bash\npip install flask-file-upload\n```\n\n*If you are updating from \u003e=0.1 then please read the [upgrading instruction](https://github.com/joegasewicz/flask-file-upload#upgrading-from-v01-to-v02)*\n\n#### General Flask config options\n(Important: The below configuration variables need to be set  before initiating `FileUpload`)\n````python\nfrom flask_file_upload.file_upload import FileUpload\nfrom os.path import join, dirname, realpath\n\n# This is the directory that flask-file-upload saves files to. Make sure the UPLOAD_FOLDER is the same as Flasks's static_folder or a child. For example:\napp.config[\"UPLOAD_FOLDER\"] = join(dirname(realpath(__file__)), \"static/uploads\")\n\n# Other FLASK config varaibles ...\napp.config[\"ALLOWED_EXTENSIONS\"] = [\"jpg\", \"png\", \"mov\", \"mp4\", \"mpg\"]\napp.config[\"MAX_CONTENT_LENGTH\"] = 1000 * 1024 * 1024  # 1000mb\napp.config[\"SQLALCHEMY_DATABASE_URI\"] = \"postgresql://localhost:5432/blog_db\"\n````\n\n#### Setup\nWe can either pass the instance to FileUpload(app) or to the init_app(app) method:\n````python\nfrom flask_file_upload import FileUpload\n\n\napp = Flask(__name__, static_folder=\"static\") # IMPORTANT: This is your root directory for serving ALL static content!\n\ndb = SQLAlchemy()\n\nfile_upload = FileUpload()\n\n# An example using the Flask factory pattern\ndef create_app():\n    db.init_app(app) \n    # Pass the Flask app instance as the 1st arg \u0026\n    # the SQLAlchemy object as the 2nd arg to file_upload.init_app.\n    file_upload.init_app(app, db)\n    \n    # If you require importing your SQLAlchemy models then make sure you import\n    # your models after calling `file_upload.init_app(app, db)` or `FileUpload(app, db)`. \n    from .model import * \n\n# Or we can pass the Flask app instance directly \u0026 the Flask-SQLAlchemy instance:\ndb = SQLAlchemy(app)\n# Pass the Flask app instance as the 1st arg \u0026\n# the SQLAlchemy object as the 2nd arg to FileUpload\nfile_upload = FileUpload(app, db)\napp: Flask = None\n````\n\n#### Decorate your SqlAlchemy models\nFlask-File-Upload (FFU) setup requires each SqlAlchemy model that wants to use FFU\nlibrary to be decorated with `@file_upload.Model` .This will enable FFU to update your\ndatabase with the extra columns required to store files in your database.\nDeclare your attributes as normal but assign a value of `file_upload.Column`.\nThis is easy if you are using Flask-SqlAlchemy:\n```python\nfrom flask_sqlalchemy import SqlAlchemy\n\ndb = SqlAlchemy()\n```\nFull example:\n ````python\nfrom my_app import file_upload\n\n@file_upload.Model\nclass blogModel(db.Model):\n    __tablename__ = \"blogs\"\n    id = db.Column(db.Integer, primary_key=True)\n\n    # Use flask-file-upload's `file_upload.Column()` to associate a file with a SQLAlchemy Model:\n    my_placeholder = file_upload.Column()\n    my_video = file_upload.Column()\n````\n\n#### define files to be uploaded:\n````python\n# A common scenario could be a video with placeholder image.\n# So first lets grab the files from Flask's request object:\nmy_video = request.files[\"my_video\"]\nplaceholder_img = request.files[\"placeholder_img\"]\n````\n\n\n#### Save files\nTo add files to your model, pass a dict of keys that reference the attribute\nname(s) defined in your SqlAlchemy model \u0026 values that are your files.\nFor Example:\n\n````python\nfile_upload.add_files(blog_post, files={\n    \"my_video\": my_video,\n    \"placeholder_img\": placeholder_img,\n})\n\n# Now commit the changes to your db\ndb.session.add(blog_post)\ndb.session.commit()\n````\nIt's always good practise to commit the changes to your db as close to the end\nof your view handlers as possible (we encourage you to use `add_files` over the `save_files`\nmethod for this reason).\n\nIf you wish to let flask-file-upload handle adding \u0026 committing to\nthe current session then use `file_upload.save_files` - this method is only recommended\nif you are sure nothing else needs committing after you have added you files.\nFor example:\n```python\nfile_upload.save_files(blog_post, files={\n    \"my_video\": my_video,\n    \"placeholder_img\": placeholder_img,\n})\n```\n##### If you followed the setup above you will see the following structure saved to your app:\n![FlaskFileUpload](assets/dir1.png?raw=true \"Directory example\")\n\n#### Update files\n````python\nblog_post = file_upload.update_files(blog_post, files={\n    \"my_video\": new_my_video,\n    \"placeholder_img\": new_placeholder_img,\n})\n````\n\n\n#### Delete files\n\nDeleting files from the db \u0026 server can be non trivial, especially to keep\nboth in sync. The `file_upload.delete_files` method can be called with a\nkwarg of `clean_up` \u0026 then depending of the string value passed it will\nprovide 2 types of clean up functionality:\n- `files` will clean up files on the server but not update the model\n- `model` will update the model but not attempt to remove the files\n   from the server.\nSee [delete_files Docs](https://flask-file-upload.readthedocs.io/en/latest/file_upload.html#flask_file_upload.file_upload.FileUpload.delete_files)\nfor more details\n````python\n# Example using a SqlAlchemy model with an appended\n# method that fetches a single `blog`\nblogModel = BlogModel()\nblog_results = blogModel.get_one()\n\n# We pass the blog \u0026 files\nblog = file_upload.delete_files(blog_result, files=[\"my_video\"])\n\n# If parent kwarg is set to True then the root primary directory \u0026 all its contents will be removed.\n# The model will also get cleaned up by default unless set to `False`.\nblog_result = file_upload.delete_files(blog_result, parent=True, files=[\"my_video\"])\n\n\n# If the kwarg `commit` is not set or set to True then the updates are persisted.\n# to the session. And therefore the session has been commited.\nblog = file_upload.delete_files(blog_result, files=[\"my_video\"])\n\n# Example of cleaning up files but not updating the model:\nblog = file_upload.delete_files(blog_result, files=[\"my_video\"], clean_up=\"files\")\n````\n\n\n#### Stream a file\n````python\nfile_upload.stream_file(blog_post, filename=\"my_video\")\n````\n\n\n#### File Url paths\n````python\nfile_upload.get_file_url(blog_post, filename=\"placeholder_img\")\n````\n\nExample for getting file urls from many objects:\n```python\n# If blogs_model are many blogs:\nfor blog in blog_models:\n    blog_image_url = file_upload.get_file_url(blog, filename=\"blog_image\")\n    setattr(blog, \"blog_image\", blog_image_url)\n```\n\n#### Set file paths to multiple objects - *Available in `0.1.0-rc.6` \u0026 `v0.1.0`*\nThe majority of requests will require many entities to be returned\n\u0026 these entities may have SQLAlchemy `backrefs` with\nrelationships that may also contain Flask-File-Upload (FFU) modified SQLAlchemy\nmodels. To make this trivial, this method will set the appropriate\nfilename urls to your SQLAlchemy model objects (if the transaction\nhasn't completed then **add_file_urls_to_models** will complete the\ntransaction by default).\n\nThe first argument required by this method is `models` - the SQLAlchemy model(s).\n\nThen pass in the required kwarg `filenames` which references the parent's\nFFU Model values - this is the `file_upload.Model` decorated SQLALchemy model\n- `file_upload.Column()` method.\n\nImportant! Also take note that each attribute set by this method postfixes\na `_url` tag. e.g `blog_image` becomes `blog_image_url`\n\nExample for many SQLAlchemy entity objects (*or rows in your table*)::\n```python\n@file_upload.Model\nclass BlogModel(db.Model):\n\n    blog_image = file_upload.Column()\n```\n\nNow we can use the `file_upload.add_file_urls_to_models` to add file urls to\neach SQLAlchemy object. For example::\n```python\nblogs = add_file_urls_to_models(blogs, filenames=\"blog_image\")\n\n# Notice that we can get the file path `blog_image` + `_url`\nassert  blogs[0].blog_image_url == \"path/to/blogs/1/blog_image_url.png\"\n```\n\nTo set filename attributes to a a single or multiple SQLAlchemy parent models with backrefs\nto multiple child SQLAlchemy models, we can assign to the optional `backref`\nkwarg the name of the backref model \u0026 a list of the file attributes we set\nwith the FFU Model decorated SQLAlchemy model.\n\nTo use backrefs we need to declare a kwarg of `backref` \u0026 pass 2 keys:\n    - **name**: The name of the backref relation\n    - **filenames**: The FFU attribute values assigned to the backref model\n\nFor example::\n```python\n# Parent model\n@file_upload.Model\nclass BlogModel(db.Model):\n    # The backref:\n    blog_news = db.relationship(\"BlogNewsModel\", backref=\"blogs\")\n    blog_image = file_upload.Column()\n    blog_video = file_upload.Column()\n\n# Model that has a foreign key back up to `BlogModel\n@file_upload.Model\nclass BlogNewsModel(db.Model):\n    # The foreign key assigned to this model:\n    blog_id = db.Column(db.Integer, db.ForeignKey(\"blogs.blog_id\"))\n    news_image = file_upload.Column()\n    news_video = file_upload.Column()\n```\n\nThe kwarg `backref` keys represent the backref model or entity (in the above example\nthis would be the `BlogNewsModel` which we have named `blog_news`. Example::\n```python\nblogs = add_file_urls_to_models(blogs, filenames=[\"blog_image, blog_video\"],\n    backref={\n        \"name\": \"blog_news\",`\n        \"filenames\": [\"news_image\", \"news_video],\n})\n```\n\nWARNING: You must not set the relationship kwarg: `lazy=\"dynamic\"`!\nIf `backref` is set to *\"dynamic\"* then back-referenced entity's\nfilenames will not get set. Example::\n```python\n# This will work\nblog_news = db.relationship(\"BlogNewsModel\", backref=\"blog\")\n\n# this will NOT set filenames on your model class\nblog_news = db.relationship(\"BlogNewsModel\", backref=\"blog\", lazy=\"dynamic\")\n```\n\n### Running Flask-Migration After including Flask-File-Upload in your project\nThe arguments below will also run if you're using vanilla Alembic.\n```bash\nexport FLASK_APP=flask_app.py # Path to your Flask app\n\n# with pip\nflask db stamp head\nflask db migrate\nflask db upgrade\n\n# with pipenv\npipenv run flask db stamp head\npipenv run flask db migrate\npipenv run flask db upgrade\n```\n\n### Upgrading from v0.1 to v0.2\nYou will need to create a migration script with the below column name changes:\n- `[you_file_name]__file_type` becomes `[you_file_name]__mime_type`\n- `[you_file_name]__mime_type` becomes `[you_file_name]__ext`\n- `[you_file_name]__file_name` stays the same\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoegasewicz%2Fflask-file-upload","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoegasewicz%2Fflask-file-upload","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoegasewicz%2Fflask-file-upload/lists"}