Package: django-castor
# `django-castor``django-castor` is a re-usable app for Django which provides a**content-addressable storage backend**. The main class,`djcastor.storage.CAStorage`, is a type of `FileSystemStorage` which saves filesunder their SHA-1 digest.*   No matter how many times the same file is uploaded, it will only ever bestored once, thus eliminating redundancy.*   Filenames are pseudorandom and made up only of hexadecimal characters, soyou don’t have to worry about filename collisions or sanitization.*   `django-castor` shards files in the uploads directory based on theirdigests; this prevents filesystem issues when too many files are in a singledirectory.For more information on the CAS concept, see the [wikipedia page][].[wikipedia page]: http://en.wikipedia.org/wiki/Content-addressable_storage## Installationpip install django-castor  # oreasy_install django-castor## UsageBasic usage is as follows:from django.db import modelsfrom djcastor import CAStorageclass MyModel(models.Model):...uploaded_file = models.FileField(storage=CAStorage(),upload_to='uploads')At the moment, Django requires a non-empty value for the `upload_to` parameter.Note that `CAStorage` will **not** use this value; if you need to customize thedestination for uploaded files, use the `location` parameter (see below).For extended usage, there are several options you can pass to the `CAStorage`constructor. The first two are inherited from the built-in `FileSystemStorage`:*   `location`: The absolute path to the directory that will hold uploadedfiles. If omitted, this will be set to the value of the `MEDIA_ROOT`setting.*   `base_url`: The URL that serves the files stored at this location. Ifomitted, this will be set to the value of the `MEDIA_URL` setting.`CAStorage` also adds two custom options:*   `keep_extension` (default `True`): Preserve the extension on uploaded files.This allows the webserver to guess their `Content-Type`.*   `sharding` (default `(2, 2)`): The width and depth to use when shardingdigests, expressed as a two-tuple. The following examples show how theseparameters affect the sharding:>>> digest = '1f09d30c707d53f3d16c530dd73d70a6ce7596a9'>>> print shard(digest, width=2, depth=2)1f/09/1f09d30c707d53f3d16c530dd73d70a6ce7596a9>>> print shard(digest, width=2, depth=3)1f/09/d3/1f09d30c707d53f3d16c530dd73d70a6ce7596a9>>> print shard(digest, width=3, depth=2)1f0/9d3/1f09d30c707d53f3d16c530dd73d70a6ce7596a9## CaveatsThe first small caveat is that content-addressable storage is not suited torapidly-changing content. If your website modifies the contents of file fieldson a regular basis, it might be a better idea to use a UUID-based storagebackend for those fields.The second, more important caveat with this approach is that if the parent modelof a file is deleted, the file will remain on disk. Because individual files maybe referred to by more than one model, and `django-castor` has no awareness ofthese references, it leaves file deletion up to the developer.For the most part, you can get away without deleting uploads. In fact,content-addressable storage is often used for long-term archival systems, wherefiles are immutable and must be kept for future auditing (usually for compliancewith government regulations).If disk space is at a premium and you need to delete uploads, there are twoapproaches you might want to take:*   Garbage collection: write a script that walks through the list of uploadedfiles and checks references to each one. If no references are found, deletethe file.*   Reference counting: denormalize the `FileField` into a separate model, andkeep a count of all the models pointing to it. Once this count reaches zero,delete the file from the filesystem.## (Un)licenseThis is free and unencumbered software released into the public domain.Anyone is free to copy, modify, publish, use, compile, sell, or distribute thissoftware, either in source code form or as a compiled binary, for any purpose,commercial or non-commercial, and by any means.In jurisdictions that recognize copyright laws, the author or authors of thissoftware dedicate any and all copyright interest in the software to the publicdomain. We make this dedication for the benefit of the public at large and tothe detriment of our heirs and successors. We intend this dedication to be anovert act of relinquishment in perpetuity of all present and future rights tothis software under copyright law.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS ORIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESSFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BELIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OFCONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THESOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.For more information, please refer to <http://unlicense.org/>