Comments (10)
Django's FileField uses a couple different components to implement file storage:
FileField
: the actual column that stores filesStorage
: an object that represents a storage space (eg. Filesystem, Dropbox, etc.)File
: a file-like object, with an unknown storage place.
Personally I think that File
is redundant, and the interface should accept any file-like object, but django's implementation does allow for the istream and ostream distinction, as well as a guaranteed way to access file metadata (filesize, created time, etc.).
The Storage
concept makes it persistence layer agnostic, but the interface has a bunch of things that make no sense. Here's my attempt at cleaning it up and making it more sqlalchemy-esque:
class CustomStorage(Storage):
# Mandatory methods:
def display_name(self, db_value):
# Takes the value stored in the sqlalchemy database and returns
# the user friendly name (usually the filename).
# This allows for storage via complex systems like CMIS, where it
# makes more sense to store an identifier in the database rather than
# the filename.
def save(self, name, file_like_object):
# Takes the file like object and persists it to the storage layer.
# Returns an identifier that can be saved in the database.
def open(self, db_value):
# Returns a file like object representing the value in the database.
# Perhaps this method could take a mode (read/write/binary/append)
# and return an istream/ostream?
def delete(self, db_value):
# Delete the file from the storage
# Non-mandatory methods:
def accessed_time(self, db_value):
# Returns a datetime() object representing the last accessed time.
def created_time(self, db_value):
# Returns a datetime() object representing the created time.
def modified_time(self, db_value):
# Returns a datetime() object representing the modified time.
def size(self, db_value):
# Returns the size of the file in bytes.
It could be used in the construction of a column like so:
class Document(Base):
# File with a custom storage layer
custom_file = sa.Column(util.FileType(storage=CustomStorage))
# File stored locally
local_file = sa.Column(util.FileType(storage=FileSystemStorage(folder="/srv/media/")))
# File stored in the database (postgres blob type?)
db_file = sa.Column(util.DatabaseFileType)
Disclaimer: my usecase involves remote CMIS storage, so that is my focus when creating this.
Thoughts?
from sqlalchemy-utils.
Looks very good. I think SQLAlchemy-Utils should only provide the basic storage interface. File storaging should be in another package which could provide drivers for different backends just as you suggested.
from sqlalchemy-utils.
This could get pretty big and perhaps deserves its own repo (for the storage layers) that depend on sqlalchemy-utils. Though a big package depending on something named sqlalchemy-utils
for the interface just feels weird (but I suppose its fine).
Do you think sqlalchemy would be open to https://github.com/sqlalchemy-contrib/ or https://github.com/sqlalchemy-ext/ ? Mostly to collect all of these things under an org. Further perhaps adding (I'm not sure if its already there) something like flask.ext to sqlalchemy so people could get this project by from sqlalchemy.ext import utils
. (Just random various ideas).
from sqlalchemy-utils.
I haven't yet contacted Mike Bayer about these packages. I will soon though, maybe at that point I could ask about how he feels these extensions should be organized. I like the idea about sqlalchemy.ext, that's what I've been missing too :)
from sqlalchemy-utils.
If we're going to split them up into different packages, then perhaps the file storaging package should contain the basic storage layer, file types, and common drivers (like the filesystem storage driver). SQLAlchemy-Utils would then provide specialized drivers (such as a CMIS or dropbox driver). That seems to be more in theme with what SQLAlchemy-Utils is providing. It would also remove the strange dependency that @mehcode was referring to.
from sqlalchemy-utils.
Additional drivers should be extensions of this storage package - not part of utils. SQLAlchemy-Utils doesn't need to have dependency on this storage package and storage package doesn't need to have dependency on SQLAlchemy-Utils.
Let's make things pythonic. SQLAlchemy-Utils should provide an interface for the storage layer merely for documentation purposes. The storage libraries need not to actually subclass this interface. It just needs to provide certain methods.
Remember the python way: If it walks like duck and quacks like a duck, treat it like a duck.
:)
from sqlalchemy-utils.
That works for me. I'll finish building it and submit a PR later.
from sqlalchemy-utils.
I've been having discussions with @jpvanhal. This will be implemented using the wonderful silo package: https://github.com/jpvanhal/siilo 🚋
from sqlalchemy-utils.
The silo package just got its initial release, so we can start implementing this. I thought that maybe its better to have FileModel instead of FileType. We could save a lot meta information about the files in this generic file model.
from sqlalchemy-utils.
Closing due to inactivity.
from sqlalchemy-utils.
Related Issues (20)
- Unable to call refresh_materialized_view on CRDB w/SQLAlchemy 2.0 HOT 1
- Create SECURITY.md
- CompositeType support for pg8000 and psycopg3 HOT 1
- create_view not accepting `replace` argument HOT 2
- Helper functions for explicit table locks ?
- custom aggregated column does not work with nullable=False
- Database_exist not working in python 3.11 HOT 1
- Even though binary was set false, impl remain binary(16)
- generic_relationship breaks with SqlAlchemy 2.0.22 HOT 3
- [Feature] Add MySQL collation support in `create_database`
- DeprecationWarning: 'crypt' is deprecated HOT 1
- Issue with change of implementation of EncryptedType from ‘LargeBinary’ to ‘String’ HOT 1
- [Feature] Enable Cascade Behavior for generic_relationship
- [Question] how to encrypt using aws kms in sqlalchemy
- Error on model with `server_default` for `DateTime` column and `UUIDType` primary key.
- [Feature] database helpers functions don't support custom create_engine()
- New release for SQLAlchemy >= 2.0.22 HOT 19
- Issue updating aggregate when setting foreign key to Null HOT 1
- Password checking error when using SQLAlchemy and Postgres
- [Feature] `auto_delete_orphans` not support `back_populates` HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sqlalchemy-utils.